- Sync with trunk r58248 to bring the latest changes from Amine (headers) and others...
[reactos.git] / dll / directx / wine / ddraw / device.c
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
6 *
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.
11 *
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.
16 *
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
20 *
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.
27 *
28 */
29
30 #include <config.h>
31 #include <wine/port.h>
32
33 #include "ddraw_private.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
36 WINE_DECLARE_DEBUG_CHANNEL(winediag);
37
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 }
44 };
45
46 static inline void set_fpu_control_word(WORD fpucw)
47 {
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
53 }
54
55 static inline WORD d3d_fpu_setup(void)
56 {
57 WORD oldcw;
58
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)
66 {
67 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
68 warned = TRUE;
69 }
70 return 0;
71 #endif
72
73 set_fpu_control_word(0x37f);
74
75 return oldcw;
76 }
77
78 static inline struct d3d_device *impl_from_IUnknown(IUnknown *iface)
79 {
80 return CONTAINING_RECORD(iface, struct d3d_device, IUnknown_inner);
81 }
82
83 static HRESULT WINAPI d3d_device_inner_QueryInterface(IUnknown *iface, REFIID riid, void **out)
84 {
85 struct d3d_device *device = impl_from_IUnknown(iface);
86
87 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
88
89 if (!riid)
90 {
91 *out = NULL;
92 return DDERR_INVALIDPARAMS;
93 }
94
95 if (IsEqualGUID(&IID_IUnknown, riid))
96 {
97 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
98 *out = &device->IDirect3DDevice7_iface;
99 return S_OK;
100 }
101
102 if (device->version == 7)
103 {
104 if (IsEqualGUID(&IID_IDirect3DDevice7, riid))
105 {
106 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
107 *out = &device->IDirect3DDevice7_iface;
108 return S_OK;
109 }
110 }
111 else
112 {
113 if (IsEqualGUID(&IID_IDirect3DDevice3, riid) && device->version == 3)
114 {
115 IDirect3DDevice3_AddRef(&device->IDirect3DDevice3_iface);
116 *out = &device->IDirect3DDevice3_iface;
117 return S_OK;
118 }
119
120 if (IsEqualGUID(&IID_IDirect3DDevice2, riid) && device->version >= 2)
121 {
122 IDirect3DDevice2_AddRef(&device->IDirect3DDevice2_iface);
123 *out = &device->IDirect3DDevice2_iface;
124 return S_OK;
125 }
126
127 if (IsEqualGUID(&IID_IDirect3DDevice, riid))
128 {
129 IDirect3DDevice_AddRef(&device->IDirect3DDevice_iface);
130 *out = &device->IDirect3DDevice_iface;
131 return S_OK;
132 }
133 }
134
135 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
136
137 *out = NULL;
138 return E_NOINTERFACE;
139 }
140
141 static HRESULT WINAPI d3d_device7_QueryInterface(IDirect3DDevice7 *iface, REFIID riid, void **out)
142 {
143 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
144
145 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
146
147 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
148 }
149
150 static HRESULT WINAPI d3d_device3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid, void **out)
151 {
152 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
153
154 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
155
156 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
157 }
158
159 static HRESULT WINAPI d3d_device2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid, void **out)
160 {
161 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
162
163 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
164
165 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
166 }
167
168 static HRESULT WINAPI d3d_device1_QueryInterface(IDirect3DDevice *iface, REFIID riid, void **out)
169 {
170 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
171
172 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
173
174 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
175 }
176
177 static ULONG WINAPI d3d_device_inner_AddRef(IUnknown *iface)
178 {
179 struct d3d_device *device = impl_from_IUnknown(iface);
180 ULONG ref = InterlockedIncrement(&device->ref);
181
182 TRACE("%p increasing refcount to %u.\n", device, ref);
183
184 return ref;
185 }
186
187 static ULONG WINAPI d3d_device7_AddRef(IDirect3DDevice7 *iface)
188 {
189 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
190
191 TRACE("iface %p.\n", iface);
192
193 return IUnknown_AddRef(device->outer_unknown);
194 }
195
196 static ULONG WINAPI d3d_device3_AddRef(IDirect3DDevice3 *iface)
197 {
198 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
199
200 TRACE("iface %p.\n", iface);
201
202 return IUnknown_AddRef(device->outer_unknown);
203 }
204
205 static ULONG WINAPI d3d_device2_AddRef(IDirect3DDevice2 *iface)
206 {
207 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
208
209 TRACE("iface %p.\n", iface);
210
211 return IUnknown_AddRef(device->outer_unknown);
212 }
213
214 static ULONG WINAPI d3d_device1_AddRef(IDirect3DDevice *iface)
215 {
216 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
217
218 TRACE("iface %p.\n", iface);
219
220 return IUnknown_AddRef(device->outer_unknown);
221 }
222
223 static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
224 {
225 struct d3d_device *This = impl_from_IUnknown(iface);
226 ULONG ref = InterlockedDecrement(&This->ref);
227
228 TRACE("%p decreasing refcount to %u.\n", This, ref);
229
230 /* This method doesn't destroy the wined3d device, because it's still in
231 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
232 * wined3d device when the render target is released. */
233 if (!ref)
234 {
235 DWORD i;
236
237 wined3d_mutex_lock();
238
239 /* There is no need to unset any resources here, wined3d will take
240 * care of that on uninit_3d(). */
241
242 /* Free the index buffer. */
243 wined3d_buffer_decref(This->indexbuffer);
244
245 /* Set the device up to render to the front buffer since the back
246 * buffer will vanish soon. */
247 wined3d_device_set_render_target(This->wined3d_device, 0,
248 This->ddraw->wined3d_frontbuffer, TRUE);
249
250 /* Release the wined3d device. This won't destroy it. */
251 if (!wined3d_device_decref(This->wined3d_device))
252 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
253
254 /* The texture handles should be unset by now, but there might be some bits
255 * missing in our reference counting(needs test). Do a sanity check. */
256 for (i = 0; i < This->handle_table.entry_count; ++i)
257 {
258 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
259
260 switch (entry->type)
261 {
262 case DDRAW_HANDLE_FREE:
263 break;
264
265 case DDRAW_HANDLE_MATERIAL:
266 {
267 struct d3d_material *m = entry->object;
268 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
269 m->Handle = 0;
270 break;
271 }
272
273 case DDRAW_HANDLE_MATRIX:
274 {
275 /* No FIXME here because this might happen because of sloppy applications. */
276 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
277 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
278 break;
279 }
280
281 case DDRAW_HANDLE_STATEBLOCK:
282 {
283 /* No FIXME here because this might happen because of sloppy applications. */
284 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
285 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
286 break;
287 }
288
289 case DDRAW_HANDLE_SURFACE:
290 {
291 struct ddraw_surface *surf = entry->object;
292 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
293 surf->Handle = 0;
294 break;
295 }
296
297 default:
298 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
299 break;
300 }
301 }
302
303 ddraw_handle_table_destroy(&This->handle_table);
304
305 TRACE("Releasing target %p.\n", This->target);
306 /* Release the render target. */
307 if (This->version != 1)
308 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
309 TRACE("Target release done\n");
310
311 This->ddraw->d3ddevice = NULL;
312
313 /* Now free the structure */
314 HeapFree(GetProcessHeap(), 0, This);
315 wined3d_mutex_unlock();
316 }
317
318 TRACE("Done\n");
319 return ref;
320 }
321
322 static ULONG WINAPI d3d_device7_Release(IDirect3DDevice7 *iface)
323 {
324 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
325
326 TRACE("iface %p.\n", iface);
327
328 return IUnknown_Release(device->outer_unknown);
329 }
330
331 static ULONG WINAPI d3d_device3_Release(IDirect3DDevice3 *iface)
332 {
333 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
334
335 TRACE("iface %p.\n", iface);
336
337 return IUnknown_Release(device->outer_unknown);
338 }
339
340 static ULONG WINAPI d3d_device2_Release(IDirect3DDevice2 *iface)
341 {
342 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
343
344 TRACE("iface %p.\n", iface);
345
346 return IUnknown_Release(device->outer_unknown);
347 }
348
349 static ULONG WINAPI d3d_device1_Release(IDirect3DDevice *iface)
350 {
351 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
352
353 TRACE("iface %p.\n", iface);
354
355 return IUnknown_Release(device->outer_unknown);
356 }
357
358 /*****************************************************************************
359 * IDirect3DDevice Methods
360 *****************************************************************************/
361
362 /*****************************************************************************
363 * IDirect3DDevice::Initialize
364 *
365 * Initializes a Direct3DDevice. This implementation is a no-op, as all
366 * initialization is done at create time.
367 *
368 * Exists in Version 1
369 *
370 * Parameters:
371 * No idea what they mean, as the MSDN page is gone
372 *
373 * Returns: DD_OK
374 *
375 *****************************************************************************/
376 static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface,
377 IDirect3D *d3d, GUID *guid, D3DDEVICEDESC *device_desc)
378 {
379 /* It shouldn't be crucial, but print a FIXME, I'm interested if
380 * any game calls it and when. */
381 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
382 iface, d3d, debugstr_guid(guid), device_desc);
383
384 return D3D_OK;
385 }
386
387 /*****************************************************************************
388 * IDirect3DDevice7::GetCaps
389 *
390 * Retrieves the device's capabilities
391 *
392 * This implementation is used for Version 7 only, the older versions have
393 * their own implementation.
394 *
395 * Parameters:
396 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
397 *
398 * Returns:
399 * D3D_OK on success
400 * D3DERR_* if a problem occurs. See WineD3D
401 *
402 *****************************************************************************/
403 static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *Desc)
404 {
405 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
406 D3DDEVICEDESC OldDesc;
407
408 TRACE("iface %p, device_desc %p.\n", iface, Desc);
409
410 if (!Desc)
411 {
412 WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
413 return DDERR_INVALIDPARAMS;
414 }
415
416 /* Call the same function used by IDirect3D, this saves code */
417 return IDirect3DImpl_GetCaps(device->ddraw->wined3d, &OldDesc, Desc);
418 }
419
420 static HRESULT WINAPI d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
421 {
422 return d3d_device7_GetCaps(iface, desc);
423 }
424
425 static HRESULT WINAPI d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
426 {
427 HRESULT hr;
428 WORD old_fpucw;
429
430 old_fpucw = d3d_fpu_setup();
431 hr = d3d_device7_GetCaps(iface, desc);
432 set_fpu_control_word(old_fpucw);
433
434 return hr;
435 }
436 /*****************************************************************************
437 * IDirect3DDevice3::GetCaps
438 *
439 * Retrieves the capabilities of the hardware device and the emulation
440 * device. For Wine, hardware and emulation are the same (it's all HW).
441 *
442 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
443 *
444 * Parameters:
445 * HWDesc: Structure to fill with the HW caps
446 * HelDesc: Structure to fill with the hardware emulation caps
447 *
448 * Returns:
449 * D3D_OK on success
450 * D3DERR_* if a problem occurs. See WineD3D
451 *
452 *****************************************************************************/
453
454 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
455 * Microsoft just expanded the existing structure without naming them
456 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
457 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
458 * one with 252 bytes.
459 *
460 * All 3 versions are allowed as parameters and only the specified amount of
461 * bytes is written.
462 *
463 * Note that Direct3D7 and earlier are not available in native Win64
464 * ddraw.dll builds, so possible size differences between 32 bit and
465 * 64 bit are a non-issue.
466 */
467 static inline BOOL check_d3ddevicedesc_size(DWORD size)
468 {
469 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
470 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
471 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
472 return FALSE;
473 }
474
475 static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
476 D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc)
477 {
478 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
479 D3DDEVICEDESC oldDesc;
480 D3DDEVICEDESC7 newDesc;
481 HRESULT hr;
482
483 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
484
485 if (!HWDesc)
486 {
487 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
488 return DDERR_INVALIDPARAMS;
489 }
490 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
491 {
492 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
493 return DDERR_INVALIDPARAMS;
494 }
495 if (!HelDesc)
496 {
497 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
498 return DDERR_INVALIDPARAMS;
499 }
500 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
501 {
502 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
503 return DDERR_INVALIDPARAMS;
504 }
505
506 hr = IDirect3DImpl_GetCaps(device->ddraw->wined3d, &oldDesc, &newDesc);
507 if (hr != D3D_OK)
508 return hr;
509
510 DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
511 DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
512 return D3D_OK;
513 }
514
515 static HRESULT WINAPI d3d_device2_GetCaps(IDirect3DDevice2 *iface,
516 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
517 {
518 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
519
520 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
521
522 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
523 }
524
525 static HRESULT WINAPI d3d_device1_GetCaps(IDirect3DDevice *iface,
526 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
527 {
528 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
529
530 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
531
532 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
533 }
534
535 /*****************************************************************************
536 * IDirect3DDevice2::SwapTextureHandles
537 *
538 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
539 *
540 * Parameters:
541 * Tex1, Tex2: The 2 Textures to swap
542 *
543 * Returns:
544 * D3D_OK
545 *
546 *****************************************************************************/
547 static HRESULT WINAPI d3d_device2_SwapTextureHandles(IDirect3DDevice2 *iface,
548 IDirect3DTexture2 *tex1, IDirect3DTexture2 *tex2)
549 {
550 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
551 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(tex1);
552 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(tex2);
553 DWORD h1, h2;
554
555 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
556
557 wined3d_mutex_lock();
558
559 h1 = surf1->Handle - 1;
560 h2 = surf2->Handle - 1;
561 device->handle_table.entries[h1].object = surf2;
562 device->handle_table.entries[h2].object = surf1;
563 surf2->Handle = h1 + 1;
564 surf1->Handle = h2 + 1;
565
566 wined3d_mutex_unlock();
567
568 return D3D_OK;
569 }
570
571 static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface,
572 IDirect3DTexture *tex1, IDirect3DTexture *tex2)
573 {
574 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
575 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(tex1);
576 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(tex2);
577 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
578 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
579
580 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
581
582 return d3d_device2_SwapTextureHandles(&device->IDirect3DDevice2_iface, t1, t2);
583 }
584
585 /*****************************************************************************
586 * IDirect3DDevice3::GetStats
587 *
588 * This method seems to retrieve some stats from the device.
589 * The MSDN documentation doesn't exist any more, but the D3DSTATS
590 * structure suggests that the amount of drawn primitives and processed
591 * vertices is returned.
592 *
593 * Exists in Version 1, 2 and 3
594 *
595 * Parameters:
596 * Stats: Pointer to a D3DSTATS structure to be filled
597 *
598 * Returns:
599 * D3D_OK on success
600 * DDERR_INVALIDPARAMS if Stats == NULL
601 *
602 *****************************************************************************/
603 static HRESULT WINAPI d3d_device3_GetStats(IDirect3DDevice3 *iface, D3DSTATS *Stats)
604 {
605 FIXME("iface %p, stats %p stub!\n", iface, Stats);
606
607 if(!Stats)
608 return DDERR_INVALIDPARAMS;
609
610 /* Fill the Stats with 0 */
611 Stats->dwTrianglesDrawn = 0;
612 Stats->dwLinesDrawn = 0;
613 Stats->dwPointsDrawn = 0;
614 Stats->dwSpansDrawn = 0;
615 Stats->dwVerticesProcessed = 0;
616
617 return D3D_OK;
618 }
619
620 static HRESULT WINAPI d3d_device2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *stats)
621 {
622 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
623
624 TRACE("iface %p, stats %p.\n", iface, stats);
625
626 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
627 }
628
629 static HRESULT WINAPI d3d_device1_GetStats(IDirect3DDevice *iface, D3DSTATS *stats)
630 {
631 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
632
633 TRACE("iface %p, stats %p.\n", iface, stats);
634
635 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
636 }
637
638 /*****************************************************************************
639 * IDirect3DDevice::CreateExecuteBuffer
640 *
641 * Creates an IDirect3DExecuteBuffer, used for rendering with a
642 * Direct3DDevice.
643 *
644 * Version 1 only.
645 *
646 * Params:
647 * Desc: Buffer description
648 * ExecuteBuffer: Address to return the Interface pointer at
649 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
650 * support
651 *
652 * Returns:
653 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
654 * DDERR_OUTOFMEMORY if we ran out of memory
655 * D3D_OK on success
656 *
657 *****************************************************************************/
658 static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface,
659 D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown)
660 {
661 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
662 struct d3d_execute_buffer *object;
663 HRESULT hr;
664
665 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
666 iface, buffer_desc, ExecuteBuffer, outer_unknown);
667
668 if (outer_unknown)
669 return CLASS_E_NOAGGREGATION;
670
671 /* Allocate the new Execute Buffer */
672 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
673 if(!object)
674 {
675 ERR("Failed to allocate execute buffer memory.\n");
676 return DDERR_OUTOFMEMORY;
677 }
678
679 hr = d3d_execute_buffer_init(object, device, buffer_desc);
680 if (FAILED(hr))
681 {
682 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
683 HeapFree(GetProcessHeap(), 0, object);
684 return hr;
685 }
686
687 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
688
689 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
690
691 return D3D_OK;
692 }
693
694 /*****************************************************************************
695 * IDirect3DDevice::Execute
696 *
697 * Executes all the stuff in an execute buffer.
698 *
699 * Params:
700 * ExecuteBuffer: The buffer to execute
701 * Viewport: The viewport used for rendering
702 * Flags: Some flags
703 *
704 * Returns:
705 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
706 * D3D_OK on success
707 *
708 *****************************************************************************/
709 static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface,
710 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags)
711 {
712 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
713 struct d3d_execute_buffer *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
714 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport);
715 HRESULT hr;
716
717 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags);
718
719 if(!buffer)
720 return DDERR_INVALIDPARAMS;
721
722 /* Execute... */
723 wined3d_mutex_lock();
724 hr = d3d_execute_buffer_execute(buffer, device, viewport_impl);
725 wined3d_mutex_unlock();
726
727 return hr;
728 }
729
730 /*****************************************************************************
731 * IDirect3DDevice3::AddViewport
732 *
733 * Add a Direct3DViewport to the device's viewport list. These viewports
734 * are wrapped to IDirect3DDevice7 viewports in viewport.c
735 *
736 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
737 * are the same interfaces.
738 *
739 * Params:
740 * Viewport: The viewport to add
741 *
742 * Returns:
743 * DDERR_INVALIDPARAMS if Viewport == NULL
744 * D3D_OK on success
745 *
746 *****************************************************************************/
747 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
748 {
749 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
750 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
751
752 TRACE("iface %p, viewport %p.\n", iface, viewport);
753
754 /* Sanity check */
755 if(!vp)
756 return DDERR_INVALIDPARAMS;
757
758 wined3d_mutex_lock();
759 list_add_head(&device->viewport_list, &vp->entry);
760 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
761 vp->active_device = device;
762 wined3d_mutex_unlock();
763
764 return D3D_OK;
765 }
766
767 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
768 IDirect3DViewport2 *viewport)
769 {
770 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
771 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
772
773 TRACE("iface %p, viewport %p.\n", iface, viewport);
774
775 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
776 }
777
778 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
779 {
780 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
781 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
782
783 TRACE("iface %p, viewport %p.\n", iface, viewport);
784
785 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
786 }
787
788 /*****************************************************************************
789 * IDirect3DDevice3::DeleteViewport
790 *
791 * Deletes a Direct3DViewport from the device's viewport list.
792 *
793 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
794 * are equal.
795 *
796 * Params:
797 * Viewport: The viewport to delete
798 *
799 * Returns:
800 * D3D_OK on success
801 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
802 *
803 *****************************************************************************/
804 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
805 {
806 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
807 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
808
809 TRACE("iface %p, viewport %p.\n", iface, viewport);
810
811 wined3d_mutex_lock();
812
813 if (vp->active_device != device)
814 {
815 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
816 wined3d_mutex_unlock();
817 return DDERR_INVALIDPARAMS;
818 }
819
820 vp->active_device = NULL;
821 list_remove(&vp->entry);
822
823 wined3d_mutex_unlock();
824
825 return D3D_OK;
826 }
827
828 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
829 {
830 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
831 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
832
833 TRACE("iface %p, viewport %p.\n", iface, viewport);
834
835 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
836 }
837
838 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
839 {
840 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
841 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
842
843 TRACE("iface %p, viewport %p.\n", iface, viewport);
844
845 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
846 }
847
848 /*****************************************************************************
849 * IDirect3DDevice3::NextViewport
850 *
851 * Returns a viewport from the viewport list, depending on the
852 * passed viewport and the flags.
853 *
854 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
855 * are equal.
856 *
857 * Params:
858 * Viewport: Viewport to use for beginning the search
859 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
860 *
861 * Returns:
862 * D3D_OK on success
863 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
864 *
865 *****************************************************************************/
866 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
867 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
868 {
869 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
870 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
871 struct d3d_viewport *next;
872 struct list *entry;
873
874 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
875 iface, Viewport3, lplpDirect3DViewport3, flags);
876
877 if(!vp)
878 {
879 *lplpDirect3DViewport3 = NULL;
880 return DDERR_INVALIDPARAMS;
881 }
882
883
884 wined3d_mutex_lock();
885 switch (flags)
886 {
887 case D3DNEXT_NEXT:
888 entry = list_next(&This->viewport_list, &vp->entry);
889 break;
890
891 case D3DNEXT_HEAD:
892 entry = list_head(&This->viewport_list);
893 break;
894
895 case D3DNEXT_TAIL:
896 entry = list_tail(&This->viewport_list);
897 break;
898
899 default:
900 WARN("Invalid flags %#x.\n", flags);
901 *lplpDirect3DViewport3 = NULL;
902 wined3d_mutex_unlock();
903 return DDERR_INVALIDPARAMS;
904 }
905
906 if (entry)
907 {
908 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
909 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
910 }
911 else
912 *lplpDirect3DViewport3 = NULL;
913
914 wined3d_mutex_unlock();
915
916 return D3D_OK;
917 }
918
919 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
920 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
921 {
922 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
923 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
924 IDirect3DViewport3 *res;
925 HRESULT hr;
926
927 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
928 iface, viewport, next, flags);
929
930 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
931 &vp->IDirect3DViewport3_iface, &res, flags);
932 *next = (IDirect3DViewport2 *)res;
933 return hr;
934 }
935
936 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
937 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
938 {
939 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
940 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
941 IDirect3DViewport3 *res;
942 HRESULT hr;
943
944 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
945 iface, viewport, next, flags);
946
947 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
948 &vp->IDirect3DViewport3_iface, &res, flags);
949 *next = (IDirect3DViewport *)res;
950 return hr;
951 }
952
953 /*****************************************************************************
954 * IDirect3DDevice::Pick
955 *
956 * Executes an execute buffer without performing rendering. Instead, a
957 * list of primitives that intersect with (x1,y1) of the passed rectangle
958 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
959 * this list.
960 *
961 * Version 1 only
962 *
963 * Params:
964 * ExecuteBuffer: Buffer to execute
965 * Viewport: Viewport to use for execution
966 * Flags: None are defined, according to the SDK
967 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
968 * x2 and y2 are ignored.
969 *
970 * Returns:
971 * D3D_OK because it's a stub
972 *
973 *****************************************************************************/
974 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
975 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
976 {
977 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
978 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
979
980 return D3D_OK;
981 }
982
983 /*****************************************************************************
984 * IDirect3DDevice::GetPickRecords
985 *
986 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
987 *
988 * Version 1 only
989 *
990 * Params:
991 * Count: Pointer to a DWORD containing the numbers of pick records to
992 * retrieve
993 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
994 *
995 * Returns:
996 * D3D_OK, because it's a stub
997 *
998 *****************************************************************************/
999 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1000 DWORD *count, D3DPICKRECORD *records)
1001 {
1002 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1003
1004 return D3D_OK;
1005 }
1006
1007 /*****************************************************************************
1008 * IDirect3DDevice7::EnumTextureformats
1009 *
1010 * Enumerates the supported texture formats. It has a list of all possible
1011 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1012 * WineD3D supports it. If so, then it is passed to the app.
1013 *
1014 * This is for Version 7 and 3, older versions have a different
1015 * callback function and their own implementation
1016 *
1017 * Params:
1018 * Callback: Callback to call for each enumerated format
1019 * Arg: Argument to pass to the callback
1020 *
1021 * Returns:
1022 * D3D_OK on success
1023 * DDERR_INVALIDPARAMS if Callback == NULL
1024 *
1025 *****************************************************************************/
1026 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1027 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1028 {
1029 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1030 struct wined3d_display_mode mode;
1031 HRESULT hr;
1032 unsigned int i;
1033
1034 static const enum wined3d_format_id FormatList[] =
1035 {
1036 /* 16 bit */
1037 WINED3DFMT_B5G5R5X1_UNORM,
1038 WINED3DFMT_B5G5R5A1_UNORM,
1039 WINED3DFMT_B4G4R4A4_UNORM,
1040 WINED3DFMT_B5G6R5_UNORM,
1041 /* 32 bit */
1042 WINED3DFMT_B8G8R8X8_UNORM,
1043 WINED3DFMT_B8G8R8A8_UNORM,
1044 /* 8 bit */
1045 WINED3DFMT_B2G3R3_UNORM,
1046 WINED3DFMT_P8_UINT,
1047 /* FOURCC codes */
1048 WINED3DFMT_DXT1,
1049 WINED3DFMT_DXT3,
1050 WINED3DFMT_DXT5,
1051 };
1052
1053 static const enum wined3d_format_id BumpFormatList[] =
1054 {
1055 WINED3DFMT_R8G8_SNORM,
1056 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1057 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1058 WINED3DFMT_R16G16_SNORM,
1059 WINED3DFMT_R10G11B11_SNORM,
1060 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1061 };
1062
1063 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1064
1065 if (!callback)
1066 return DDERR_INVALIDPARAMS;
1067
1068 wined3d_mutex_lock();
1069
1070 memset(&mode, 0, sizeof(mode));
1071 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1072 {
1073 wined3d_mutex_unlock();
1074 WARN("Cannot get the current adapter format\n");
1075 return hr;
1076 }
1077
1078 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1079 {
1080 hr = wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1081 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1082 if (hr == D3D_OK)
1083 {
1084 DDPIXELFORMAT pformat;
1085
1086 memset(&pformat, 0, sizeof(pformat));
1087 pformat.dwSize = sizeof(pformat);
1088 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1089
1090 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1091 hr = callback(&pformat, context);
1092 if(hr != DDENUMRET_OK)
1093 {
1094 TRACE("Format enumeration cancelled by application\n");
1095 wined3d_mutex_unlock();
1096 return D3D_OK;
1097 }
1098 }
1099 }
1100
1101 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1102 {
1103 hr = wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1104 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1105 WINED3D_RTYPE_TEXTURE, BumpFormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1106 if (hr == D3D_OK)
1107 {
1108 DDPIXELFORMAT pformat;
1109
1110 memset(&pformat, 0, sizeof(pformat));
1111 pformat.dwSize = sizeof(pformat);
1112 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1113
1114 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1115 hr = callback(&pformat, context);
1116 if(hr != DDENUMRET_OK)
1117 {
1118 TRACE("Format enumeration cancelled by application\n");
1119 wined3d_mutex_unlock();
1120 return D3D_OK;
1121 }
1122 }
1123 }
1124 TRACE("End of enumeration\n");
1125 wined3d_mutex_unlock();
1126
1127 return D3D_OK;
1128 }
1129
1130 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1131 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1132 {
1133 return d3d_device7_EnumTextureFormats(iface, callback, context);
1134 }
1135
1136 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1137 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1138 {
1139 HRESULT hr;
1140 WORD old_fpucw;
1141
1142 old_fpucw = d3d_fpu_setup();
1143 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1144 set_fpu_control_word(old_fpucw);
1145
1146 return hr;
1147 }
1148
1149 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1150 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1151 {
1152 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1153
1154 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1155
1156 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1157 }
1158
1159 /*****************************************************************************
1160 * IDirect3DDevice2::EnumTextureformats
1161 *
1162 * EnumTextureFormats for Version 1 and 2, see
1163 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1164 *
1165 * This version has a different callback and does not enumerate FourCC
1166 * formats
1167 *
1168 *****************************************************************************/
1169 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1170 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1171 {
1172 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1173 struct wined3d_display_mode mode;
1174 HRESULT hr;
1175 unsigned int i;
1176
1177 static const enum wined3d_format_id FormatList[] =
1178 {
1179 /* 16 bit */
1180 WINED3DFMT_B5G5R5X1_UNORM,
1181 WINED3DFMT_B5G5R5A1_UNORM,
1182 WINED3DFMT_B4G4R4A4_UNORM,
1183 WINED3DFMT_B5G6R5_UNORM,
1184 /* 32 bit */
1185 WINED3DFMT_B8G8R8X8_UNORM,
1186 WINED3DFMT_B8G8R8A8_UNORM,
1187 /* 8 bit */
1188 WINED3DFMT_B2G3R3_UNORM,
1189 WINED3DFMT_P8_UINT,
1190 /* FOURCC codes - Not in this version*/
1191 };
1192
1193 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1194
1195 if (!callback)
1196 return DDERR_INVALIDPARAMS;
1197
1198 wined3d_mutex_lock();
1199
1200 memset(&mode, 0, sizeof(mode));
1201 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1202 {
1203 wined3d_mutex_unlock();
1204 WARN("Cannot get the current adapter format\n");
1205 return hr;
1206 }
1207
1208 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1209 {
1210 hr = wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1211 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1212 if (hr == D3D_OK)
1213 {
1214 DDSURFACEDESC sdesc;
1215
1216 memset(&sdesc, 0, sizeof(sdesc));
1217 sdesc.dwSize = sizeof(sdesc);
1218 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1219 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1220 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1221 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1222
1223 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1224 hr = callback(&sdesc, context);
1225 if(hr != DDENUMRET_OK)
1226 {
1227 TRACE("Format enumeration cancelled by application\n");
1228 wined3d_mutex_unlock();
1229 return D3D_OK;
1230 }
1231 }
1232 }
1233 TRACE("End of enumeration\n");
1234 wined3d_mutex_unlock();
1235
1236 return D3D_OK;
1237 }
1238
1239 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1240 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1241 {
1242 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1243
1244 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1245
1246 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1247 }
1248
1249 /*****************************************************************************
1250 * IDirect3DDevice::CreateMatrix
1251 *
1252 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1253 * allocated for the handle.
1254 *
1255 * Version 1 only
1256 *
1257 * Params
1258 * D3DMatHandle: Address to return the handle at
1259 *
1260 * Returns:
1261 * D3D_OK on success
1262 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1263 *
1264 *****************************************************************************/
1265 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1266 {
1267 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1268 D3DMATRIX *Matrix;
1269 DWORD h;
1270
1271 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1272
1273 if(!D3DMatHandle)
1274 return DDERR_INVALIDPARAMS;
1275
1276 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1277 if(!Matrix)
1278 {
1279 ERR("Out of memory when allocating a D3DMATRIX\n");
1280 return DDERR_OUTOFMEMORY;
1281 }
1282
1283 wined3d_mutex_lock();
1284
1285 h = ddraw_allocate_handle(&device->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1286 if (h == DDRAW_INVALID_HANDLE)
1287 {
1288 ERR("Failed to allocate a matrix handle.\n");
1289 HeapFree(GetProcessHeap(), 0, Matrix);
1290 wined3d_mutex_unlock();
1291 return DDERR_OUTOFMEMORY;
1292 }
1293
1294 *D3DMatHandle = h + 1;
1295
1296 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1297
1298 wined3d_mutex_unlock();
1299
1300 return D3D_OK;
1301 }
1302
1303 /*****************************************************************************
1304 * IDirect3DDevice::SetMatrix
1305 *
1306 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1307 * allocated for the handle
1308 *
1309 * Version 1 only
1310 *
1311 * Params:
1312 * D3DMatHandle: Handle to set the matrix to
1313 * D3DMatrix: Matrix to set
1314 *
1315 * Returns:
1316 * D3D_OK on success
1317 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1318 * to set is NULL
1319 *
1320 *****************************************************************************/
1321 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1322 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1323 {
1324 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1325 D3DMATRIX *m;
1326
1327 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1328
1329 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1330
1331 wined3d_mutex_lock();
1332
1333 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1334 if (!m)
1335 {
1336 WARN("Invalid matrix handle.\n");
1337 wined3d_mutex_unlock();
1338 return DDERR_INVALIDPARAMS;
1339 }
1340
1341 if (TRACE_ON(ddraw))
1342 dump_D3DMATRIX(D3DMatrix);
1343
1344 *m = *D3DMatrix;
1345
1346 if (D3DMatHandle == This->world)
1347 wined3d_device_set_transform(This->wined3d_device,
1348 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1349
1350 if (D3DMatHandle == This->view)
1351 wined3d_device_set_transform(This->wined3d_device,
1352 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1353
1354 if (D3DMatHandle == This->proj)
1355 wined3d_device_set_transform(This->wined3d_device,
1356 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1357
1358 wined3d_mutex_unlock();
1359
1360 return D3D_OK;
1361 }
1362
1363 /*****************************************************************************
1364 * IDirect3DDevice::GetMatrix
1365 *
1366 * Returns the content of a D3DMATRIX handle
1367 *
1368 * Version 1 only
1369 *
1370 * Params:
1371 * D3DMatHandle: Matrix handle to read the content from
1372 * D3DMatrix: Address to store the content at
1373 *
1374 * Returns:
1375 * D3D_OK on success
1376 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1377 *
1378 *****************************************************************************/
1379 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1380 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1381 {
1382 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1383 D3DMATRIX *m;
1384
1385 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1386
1387 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1388
1389 wined3d_mutex_lock();
1390
1391 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1392 if (!m)
1393 {
1394 WARN("Invalid matrix handle.\n");
1395 wined3d_mutex_unlock();
1396 return DDERR_INVALIDPARAMS;
1397 }
1398
1399 *D3DMatrix = *m;
1400
1401 wined3d_mutex_unlock();
1402
1403 return D3D_OK;
1404 }
1405
1406 /*****************************************************************************
1407 * IDirect3DDevice::DeleteMatrix
1408 *
1409 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1410 *
1411 * Version 1 only
1412 *
1413 * Params:
1414 * D3DMatHandle: Handle to destroy
1415 *
1416 * Returns:
1417 * D3D_OK on success
1418 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1419 *
1420 *****************************************************************************/
1421 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1422 {
1423 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1424 D3DMATRIX *m;
1425
1426 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1427
1428 wined3d_mutex_lock();
1429
1430 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1431 if (!m)
1432 {
1433 WARN("Invalid matrix handle.\n");
1434 wined3d_mutex_unlock();
1435 return DDERR_INVALIDPARAMS;
1436 }
1437
1438 wined3d_mutex_unlock();
1439
1440 HeapFree(GetProcessHeap(), 0, m);
1441
1442 return D3D_OK;
1443 }
1444
1445 /*****************************************************************************
1446 * IDirect3DDevice7::BeginScene
1447 *
1448 * This method must be called before any rendering is performed.
1449 * IDirect3DDevice::EndScene has to be called after the scene is complete
1450 *
1451 * Version 1, 2, 3 and 7
1452 *
1453 * Returns:
1454 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1455 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1456 * started scene).
1457 *
1458 *****************************************************************************/
1459 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1460 {
1461 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1462 HRESULT hr;
1463
1464 TRACE("iface %p.\n", iface);
1465
1466 wined3d_mutex_lock();
1467 hr = wined3d_device_begin_scene(device->wined3d_device);
1468 wined3d_mutex_unlock();
1469
1470 if(hr == WINED3D_OK) return D3D_OK;
1471 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1472 }
1473
1474 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1475 {
1476 return d3d_device7_BeginScene(iface);
1477 }
1478
1479 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1480 {
1481 HRESULT hr;
1482 WORD old_fpucw;
1483
1484 old_fpucw = d3d_fpu_setup();
1485 hr = d3d_device7_BeginScene(iface);
1486 set_fpu_control_word(old_fpucw);
1487
1488 return hr;
1489 }
1490
1491 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1492 {
1493 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1494
1495 TRACE("iface %p.\n", iface);
1496
1497 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1498 }
1499
1500 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1501 {
1502 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1503
1504 TRACE("iface %p.\n", iface);
1505
1506 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1507 }
1508
1509 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1510 {
1511 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1512
1513 TRACE("iface %p.\n", iface);
1514
1515 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1516 }
1517
1518 /*****************************************************************************
1519 * IDirect3DDevice7::EndScene
1520 *
1521 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1522 * This method must be called after rendering is finished.
1523 *
1524 * Version 1, 2, 3 and 7
1525 *
1526 * Returns:
1527 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1528 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1529 * that only if the scene was already ended.
1530 *
1531 *****************************************************************************/
1532 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1533 {
1534 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1535 HRESULT hr;
1536
1537 TRACE("iface %p.\n", iface);
1538
1539 wined3d_mutex_lock();
1540 hr = wined3d_device_end_scene(device->wined3d_device);
1541 wined3d_mutex_unlock();
1542
1543 if(hr == WINED3D_OK) return D3D_OK;
1544 else return D3DERR_SCENE_NOT_IN_SCENE;
1545 }
1546
1547 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1548 {
1549 return d3d_device7_EndScene(iface);
1550 }
1551
1552 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1553 {
1554 HRESULT hr;
1555 WORD old_fpucw;
1556
1557 old_fpucw = d3d_fpu_setup();
1558 hr = d3d_device7_EndScene(iface);
1559 set_fpu_control_word(old_fpucw);
1560
1561 return hr;
1562 }
1563
1564 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1565 {
1566 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1567
1568 TRACE("iface %p.\n", iface);
1569
1570 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1571 }
1572
1573 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1574 {
1575 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1576
1577 TRACE("iface %p.\n", iface);
1578
1579 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1580 }
1581
1582 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1583 {
1584 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1585
1586 TRACE("iface %p.\n", iface);
1587
1588 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1589 }
1590
1591 /*****************************************************************************
1592 * IDirect3DDevice7::GetDirect3D
1593 *
1594 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1595 * this device.
1596 *
1597 * Params:
1598 * Direct3D7: Address to store the interface pointer at
1599 *
1600 * Returns:
1601 * D3D_OK on success
1602 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1603 *
1604 *****************************************************************************/
1605 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1606 {
1607 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1608
1609 TRACE("iface %p, d3d %p.\n", iface, d3d);
1610
1611 if (!d3d)
1612 return DDERR_INVALIDPARAMS;
1613
1614 *d3d = &device->ddraw->IDirect3D7_iface;
1615 IDirect3D7_AddRef(*d3d);
1616
1617 TRACE("Returning interface %p.\n", *d3d);
1618 return D3D_OK;
1619 }
1620
1621 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1622 {
1623 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1624
1625 TRACE("iface %p, d3d %p.\n", iface, d3d);
1626
1627 if (!d3d)
1628 return DDERR_INVALIDPARAMS;
1629
1630 *d3d = &device->ddraw->IDirect3D3_iface;
1631 IDirect3D3_AddRef(*d3d);
1632
1633 TRACE("Returning interface %p.\n", *d3d);
1634 return D3D_OK;
1635 }
1636
1637 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1638 {
1639 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1640
1641 TRACE("iface %p, d3d %p.\n", iface, d3d);
1642
1643 if (!d3d)
1644 return DDERR_INVALIDPARAMS;
1645
1646 *d3d = &device->ddraw->IDirect3D2_iface;
1647 IDirect3D2_AddRef(*d3d);
1648
1649 TRACE("Returning interface %p.\n", *d3d);
1650 return D3D_OK;
1651 }
1652
1653 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1654 {
1655 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1656
1657 TRACE("iface %p, d3d %p.\n", iface, d3d);
1658
1659 if (!d3d)
1660 return DDERR_INVALIDPARAMS;
1661
1662 *d3d = &device->ddraw->IDirect3D_iface;
1663 IDirect3D_AddRef(*d3d);
1664
1665 TRACE("Returning interface %p.\n", *d3d);
1666 return D3D_OK;
1667 }
1668
1669 /*****************************************************************************
1670 * IDirect3DDevice3::SetCurrentViewport
1671 *
1672 * Sets a Direct3DViewport as the current viewport.
1673 * For the thunks note that all viewport interface versions are equal
1674 *
1675 * Params:
1676 * Direct3DViewport3: The viewport to set
1677 *
1678 * Version 2 and 3
1679 *
1680 * Returns:
1681 * D3D_OK on success
1682 * (Is a NULL viewport valid?)
1683 *
1684 *****************************************************************************/
1685 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1686 {
1687 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1688 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1689
1690 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1691
1692 wined3d_mutex_lock();
1693 /* Do nothing if the specified viewport is the same as the current one */
1694 if (This->current_viewport == vp )
1695 {
1696 wined3d_mutex_unlock();
1697 return D3D_OK;
1698 }
1699
1700 if (vp->active_device != This)
1701 {
1702 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1703 wined3d_mutex_unlock();
1704 return DDERR_INVALIDPARAMS;
1705 }
1706
1707 /* Release previous viewport and AddRef the new one */
1708 if (This->current_viewport)
1709 {
1710 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1711 &This->current_viewport->IDirect3DViewport3_iface);
1712 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1713 }
1714 IDirect3DViewport3_AddRef(Direct3DViewport3);
1715
1716 /* Set this viewport as the current viewport */
1717 This->current_viewport = vp;
1718
1719 /* Activate this viewport */
1720 viewport_activate(This->current_viewport, FALSE);
1721
1722 wined3d_mutex_unlock();
1723
1724 return D3D_OK;
1725 }
1726
1727 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1728 {
1729 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1730 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1731
1732 TRACE("iface %p, viewport %p.\n", iface, viewport);
1733
1734 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
1735 }
1736
1737 /*****************************************************************************
1738 * IDirect3DDevice3::GetCurrentViewport
1739 *
1740 * Returns the currently active viewport.
1741 *
1742 * Version 2 and 3
1743 *
1744 * Params:
1745 * Direct3DViewport3: Address to return the interface pointer at
1746 *
1747 * Returns:
1748 * D3D_OK on success
1749 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1750 *
1751 *****************************************************************************/
1752 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1753 {
1754 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1755
1756 TRACE("iface %p, viewport %p.\n", iface, viewport);
1757
1758 if (!viewport)
1759 return DDERR_INVALIDPARAMS;
1760
1761 wined3d_mutex_lock();
1762 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1763
1764 /* AddRef the returned viewport */
1765 if (*viewport)
1766 IDirect3DViewport3_AddRef(*viewport);
1767
1768 TRACE("Returning interface %p.\n", *viewport);
1769
1770 wined3d_mutex_unlock();
1771
1772 return D3D_OK;
1773 }
1774
1775 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1776 {
1777 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1778
1779 TRACE("iface %p, viewport %p.\n", iface, viewport);
1780
1781 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1782 (IDirect3DViewport3 **)viewport);
1783 }
1784
1785 /*****************************************************************************
1786 * IDirect3DDevice7::SetRenderTarget
1787 *
1788 * Sets the render target for the Direct3DDevice.
1789 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1790 * IDirectDrawSurface3 == IDirectDrawSurface
1791 *
1792 * Version 2, 3 and 7
1793 *
1794 * Params:
1795 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1796 * render target
1797 * Flags: Some flags
1798 *
1799 * Returns:
1800 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1801 *
1802 *****************************************************************************/
1803 static HRESULT d3d_device_set_render_target(struct d3d_device *device, struct ddraw_surface *target)
1804 {
1805 HRESULT hr;
1806
1807 wined3d_mutex_lock();
1808
1809 if (device->target == target)
1810 {
1811 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1812 wined3d_mutex_unlock();
1813 return D3D_OK;
1814 }
1815 device->target = target;
1816 hr = wined3d_device_set_render_target(device->wined3d_device, 0,
1817 target ? target->wined3d_surface : NULL, FALSE);
1818 if(hr != D3D_OK)
1819 {
1820 wined3d_mutex_unlock();
1821 return hr;
1822 }
1823 d3d_device_update_depth_stencil(device);
1824
1825 wined3d_mutex_unlock();
1826
1827 return D3D_OK;
1828 }
1829
1830 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1831 IDirectDrawSurface7 *NewTarget, DWORD flags)
1832 {
1833 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1834 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1835
1836 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, flags);
1837
1838 IDirectDrawSurface7_AddRef(NewTarget);
1839 IDirectDrawSurface7_Release(&device->target->IDirectDrawSurface7_iface);
1840 return d3d_device_set_render_target(device, target);
1841 }
1842
1843 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1844 IDirectDrawSurface7 *NewTarget, DWORD flags)
1845 {
1846 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1847 }
1848
1849 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1850 IDirectDrawSurface7 *NewTarget, DWORD flags)
1851 {
1852 HRESULT hr;
1853 WORD old_fpucw;
1854
1855 old_fpucw = d3d_fpu_setup();
1856 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1857 set_fpu_control_word(old_fpucw);
1858
1859 return hr;
1860 }
1861
1862 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1863 IDirectDrawSurface4 *NewRenderTarget, DWORD flags)
1864 {
1865 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1866 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1867
1868 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1869
1870 IDirectDrawSurface4_AddRef(NewRenderTarget);
1871 IDirectDrawSurface4_Release(&device->target->IDirectDrawSurface4_iface);
1872 return d3d_device_set_render_target(device, target);
1873 }
1874
1875 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1876 IDirectDrawSurface *NewRenderTarget, DWORD flags)
1877 {
1878 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1879 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1880
1881 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1882
1883 IDirectDrawSurface_AddRef(NewRenderTarget);
1884 IDirectDrawSurface_Release(&device->target->IDirectDrawSurface_iface);
1885 return d3d_device_set_render_target(device, target);
1886 }
1887
1888 /*****************************************************************************
1889 * IDirect3DDevice7::GetRenderTarget
1890 *
1891 * Returns the current render target.
1892 * This is handled locally, because the WineD3D render target's parent
1893 * is an IParent
1894 *
1895 * Version 2, 3 and 7
1896 *
1897 * Params:
1898 * RenderTarget: Address to store the surface interface pointer
1899 *
1900 * Returns:
1901 * D3D_OK on success
1902 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1903 *
1904 *****************************************************************************/
1905 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
1906 {
1907 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1908
1909 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1910
1911 if(!RenderTarget)
1912 return DDERR_INVALIDPARAMS;
1913
1914 wined3d_mutex_lock();
1915 *RenderTarget = &device->target->IDirectDrawSurface7_iface;
1916 IDirectDrawSurface7_AddRef(*RenderTarget);
1917 wined3d_mutex_unlock();
1918
1919 return D3D_OK;
1920 }
1921
1922 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
1923 {
1924 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1925 IDirectDrawSurface7 *RenderTarget7;
1926 struct ddraw_surface *RenderTargetImpl;
1927 HRESULT hr;
1928
1929 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1930
1931 if(!RenderTarget)
1932 return DDERR_INVALIDPARAMS;
1933
1934 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1935 if(hr != D3D_OK) return hr;
1936 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1937 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1938 IDirectDrawSurface4_AddRef(*RenderTarget);
1939 IDirectDrawSurface7_Release(RenderTarget7);
1940 return D3D_OK;
1941 }
1942
1943 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
1944 {
1945 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1946 IDirectDrawSurface7 *RenderTarget7;
1947 struct ddraw_surface *RenderTargetImpl;
1948 HRESULT hr;
1949
1950 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1951
1952 if(!RenderTarget)
1953 return DDERR_INVALIDPARAMS;
1954
1955 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1956 if(hr != D3D_OK) return hr;
1957 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1958 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1959 IDirectDrawSurface_AddRef(*RenderTarget);
1960 IDirectDrawSurface7_Release(RenderTarget7);
1961 return D3D_OK;
1962 }
1963
1964 /*****************************************************************************
1965 * IDirect3DDevice3::Begin
1966 *
1967 * Begins a description block of vertices. This is similar to glBegin()
1968 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1969 * described with IDirect3DDevice::Vertex are drawn.
1970 *
1971 * Version 2 and 3
1972 *
1973 * Params:
1974 * PrimitiveType: The type of primitives to draw
1975 * VertexTypeDesc: A flexible vertex format description of the vertices
1976 * Flags: Some flags..
1977 *
1978 * Returns:
1979 * D3D_OK on success
1980 *
1981 *****************************************************************************/
1982 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
1983 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
1984 {
1985 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1986
1987 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
1988 iface, primitive_type, fvf, flags);
1989
1990 wined3d_mutex_lock();
1991 device->primitive_type = primitive_type;
1992 device->vertex_type = fvf;
1993 device->render_flags = flags;
1994 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
1995 device->nb_vertices = 0;
1996 wined3d_mutex_unlock();
1997
1998 return D3D_OK;
1999 }
2000
2001 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2002 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2003 {
2004 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2005 DWORD fvf;
2006
2007 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2008 iface, primitive_type, vertex_type, flags);
2009
2010 switch (vertex_type)
2011 {
2012 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2013 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2014 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2015 default:
2016 ERR("Unexpected vertex type %#x.\n", vertex_type);
2017 return DDERR_INVALIDPARAMS; /* Should never happen */
2018 };
2019
2020 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2021 }
2022
2023 /*****************************************************************************
2024 * IDirect3DDevice3::BeginIndexed
2025 *
2026 * Draws primitives based on vertices in a vertex array which are specified
2027 * by indices.
2028 *
2029 * Version 2 and 3
2030 *
2031 * Params:
2032 * PrimitiveType: Primitive type to draw
2033 * VertexType: A FVF description of the vertex format
2034 * Vertices: pointer to an array containing the vertices
2035 * NumVertices: The number of vertices in the vertex array
2036 * Flags: Some flags ...
2037 *
2038 * Returns:
2039 * D3D_OK, because it's a stub
2040 *
2041 *****************************************************************************/
2042 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2043 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2044 void *vertices, DWORD vertex_count, DWORD flags)
2045 {
2046 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2047 iface, primitive_type, fvf, vertices, vertex_count, flags);
2048
2049 return D3D_OK;
2050 }
2051
2052
2053 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2054 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2055 void *vertices, DWORD vertex_count, DWORD flags)
2056 {
2057 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2058 DWORD fvf;
2059
2060 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2061 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2062
2063 switch (vertex_type)
2064 {
2065 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2066 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2067 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2068 default:
2069 ERR("Unexpected vertex type %#x.\n", vertex_type);
2070 return DDERR_INVALIDPARAMS; /* Should never happen */
2071 };
2072
2073 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2074 primitive_type, fvf, vertices, vertex_count, flags);
2075 }
2076
2077 /*****************************************************************************
2078 * IDirect3DDevice3::Vertex
2079 *
2080 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2081 * drawn vertices in a vertex buffer. If the buffer is too small, its
2082 * size is increased.
2083 *
2084 * Version 2 and 3
2085 *
2086 * Params:
2087 * Vertex: Pointer to the vertex
2088 *
2089 * Returns:
2090 * D3D_OK, on success
2091 * DDERR_INVALIDPARAMS if Vertex is NULL
2092 *
2093 *****************************************************************************/
2094 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2095 {
2096 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2097
2098 TRACE("iface %p, vertex %p.\n", iface, vertex);
2099
2100 if (!vertex)
2101 return DDERR_INVALIDPARAMS;
2102
2103 wined3d_mutex_lock();
2104 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2105 {
2106 BYTE *old_buffer;
2107
2108 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2109 old_buffer = device->vertex_buffer;
2110 device->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2111 if (old_buffer)
2112 {
2113 memcpy(device->vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2114 HeapFree(GetProcessHeap(), 0, old_buffer);
2115 }
2116 }
2117
2118 memcpy(device->vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2119 wined3d_mutex_unlock();
2120
2121 return D3D_OK;
2122 }
2123
2124 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2125 {
2126 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2127
2128 TRACE("iface %p, vertex %p.\n", iface, vertex);
2129
2130 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2131 }
2132
2133 /*****************************************************************************
2134 * IDirect3DDevice3::Index
2135 *
2136 * Specifies an index to a vertex to be drawn. The vertex array has to
2137 * be specified with BeginIndexed first.
2138 *
2139 * Parameters:
2140 * VertexIndex: The index of the vertex to draw
2141 *
2142 * Returns:
2143 * D3D_OK because it's a stub
2144 *
2145 *****************************************************************************/
2146 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2147 {
2148 FIXME("iface %p, index %#x stub!\n", iface, index);
2149
2150 return D3D_OK;
2151 }
2152
2153 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2154 {
2155 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2156
2157 TRACE("iface %p, index %#x.\n", iface, index);
2158
2159 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2160 }
2161
2162 /*****************************************************************************
2163 * IDirect3DDevice3::End
2164 *
2165 * Ends a draw begun with IDirect3DDevice3::Begin or
2166 * IDirect3DDevice::BeginIndexed. The vertices specified with
2167 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2168 * the IDirect3DDevice7::DrawPrimitive method. So far only
2169 * non-indexed mode is supported
2170 *
2171 * Version 2 and 3
2172 *
2173 * Params:
2174 * Flags: Some flags, as usual. Don't know which are defined
2175 *
2176 * Returns:
2177 * The return value of IDirect3DDevice7::DrawPrimitive
2178 *
2179 *****************************************************************************/
2180 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
2181 {
2182 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2183
2184 TRACE("iface %p, flags %#x.\n", iface, flags);
2185
2186 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface, device->primitive_type,
2187 device->vertex_type, device->vertex_buffer, device->nb_vertices, device->render_flags);
2188 }
2189
2190 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
2191 {
2192 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2193
2194 TRACE("iface %p, flags %#x.\n", iface, flags);
2195
2196 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
2197 }
2198
2199 /*****************************************************************************
2200 * IDirect3DDevice7::GetRenderState
2201 *
2202 * Returns the value of a render state. The possible render states are
2203 * defined in include/d3dtypes.h
2204 *
2205 * Version 2, 3 and 7
2206 *
2207 * Params:
2208 * RenderStateType: Render state to return the current setting of
2209 * Value: Address to store the value at
2210 *
2211 * Returns:
2212 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2213 * DDERR_INVALIDPARAMS if Value == NULL
2214 *
2215 *****************************************************************************/
2216 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2217 D3DRENDERSTATETYPE state, DWORD *value)
2218 {
2219 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2220 HRESULT hr;
2221
2222 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2223
2224 if (!value)
2225 return DDERR_INVALIDPARAMS;
2226
2227 wined3d_mutex_lock();
2228 switch (state)
2229 {
2230 case D3DRENDERSTATE_TEXTUREMAG:
2231 {
2232 enum wined3d_texture_filter_type tex_mag;
2233
2234 hr = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, &tex_mag);
2235
2236 switch (tex_mag)
2237 {
2238 case WINED3D_TEXF_POINT:
2239 *value = D3DFILTER_NEAREST;
2240 break;
2241 case WINED3D_TEXF_LINEAR:
2242 *value = D3DFILTER_LINEAR;
2243 break;
2244 default:
2245 ERR("Unhandled texture mag %d !\n",tex_mag);
2246 *value = 0;
2247 }
2248 break;
2249 }
2250
2251 case D3DRENDERSTATE_TEXTUREMIN:
2252 {
2253 enum wined3d_texture_filter_type tex_min;
2254 enum wined3d_texture_filter_type tex_mip;
2255
2256 hr = wined3d_device_get_sampler_state(device->wined3d_device,
2257 0, WINED3D_SAMP_MIN_FILTER, &tex_min);
2258 if (FAILED(hr))
2259 {
2260 wined3d_mutex_unlock();
2261 return hr;
2262 }
2263 hr = wined3d_device_get_sampler_state(device->wined3d_device,
2264 0, WINED3D_SAMP_MIP_FILTER, &tex_mip);
2265
2266 switch (tex_min)
2267 {
2268 case WINED3D_TEXF_POINT:
2269 switch (tex_mip)
2270 {
2271 case WINED3D_TEXF_NONE:
2272 *value = D3DFILTER_NEAREST;
2273 break;
2274 case WINED3D_TEXF_POINT:
2275 *value = D3DFILTER_MIPNEAREST;
2276 break;
2277 case WINED3D_TEXF_LINEAR:
2278 *value = D3DFILTER_LINEARMIPNEAREST;
2279 break;
2280 default:
2281 ERR("Unhandled mip filter %#x.\n", tex_mip);
2282 *value = D3DFILTER_NEAREST;
2283 break;
2284 }
2285 break;
2286 case WINED3D_TEXF_LINEAR:
2287 switch (tex_mip)
2288 {
2289 case WINED3D_TEXF_NONE:
2290 *value = D3DFILTER_LINEAR;
2291 break;
2292 case WINED3D_TEXF_POINT:
2293 *value = D3DFILTER_MIPLINEAR;
2294 break;
2295 case WINED3D_TEXF_LINEAR:
2296 *value = D3DFILTER_LINEARMIPLINEAR;
2297 break;
2298 default:
2299 ERR("Unhandled mip filter %#x.\n", tex_mip);
2300 *value = D3DFILTER_LINEAR;
2301 break;
2302 }
2303 break;
2304 default:
2305 ERR("Unhandled texture min filter %#x.\n",tex_min);
2306 *value = D3DFILTER_NEAREST;
2307 break;
2308 }
2309 break;
2310 }
2311
2312 case D3DRENDERSTATE_TEXTUREADDRESS:
2313 case D3DRENDERSTATE_TEXTUREADDRESSU:
2314 hr = wined3d_device_get_sampler_state(device->wined3d_device,
2315 0, WINED3D_SAMP_ADDRESS_U, value);
2316 break;
2317 case D3DRENDERSTATE_TEXTUREADDRESSV:
2318 hr = wined3d_device_get_sampler_state(device->wined3d_device,
2319 0, WINED3D_SAMP_ADDRESS_V, value);
2320 break;
2321
2322 case D3DRENDERSTATE_BORDERCOLOR:
2323 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2324 hr = E_NOTIMPL;
2325 break;
2326
2327 case D3DRENDERSTATE_TEXTUREHANDLE:
2328 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2329 WARN("Render state %#x is invalid in d3d7.\n", state);
2330 hr = DDERR_INVALIDPARAMS;
2331 break;
2332
2333 case D3DRENDERSTATE_ZBIAS:
2334 hr = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2335 break;
2336
2337 default:
2338 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2339 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2340 {
2341 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2342 hr = E_NOTIMPL;
2343 break;
2344 }
2345 hr = wined3d_device_get_render_state(device->wined3d_device, state, value);
2346 }
2347 wined3d_mutex_unlock();
2348
2349 return hr;
2350 }
2351
2352 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2353 D3DRENDERSTATETYPE state, DWORD *value)
2354 {
2355 return d3d_device7_GetRenderState(iface, state, value);
2356 }
2357
2358 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2359 D3DRENDERSTATETYPE state, DWORD *value)
2360 {
2361 HRESULT hr;
2362 WORD old_fpucw;
2363
2364 old_fpucw = d3d_fpu_setup();
2365 hr = d3d_device7_GetRenderState(iface, state, value);
2366 set_fpu_control_word(old_fpucw);
2367
2368 return hr;
2369 }
2370
2371 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2372 D3DRENDERSTATETYPE state, DWORD *value)
2373 {
2374 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2375 HRESULT hr;
2376
2377 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2378
2379 switch (state)
2380 {
2381 case D3DRENDERSTATE_TEXTUREHANDLE:
2382 {
2383 /* This state is wrapped to SetTexture in SetRenderState, so
2384 * it has to be wrapped to GetTexture here. */
2385 struct wined3d_texture *tex = NULL;
2386 *value = 0;
2387
2388 wined3d_mutex_lock();
2389 hr = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
2390 if (SUCCEEDED(hr) && tex)
2391 {
2392 /* The parent of the texture is the IDirectDrawSurface7
2393 * interface of the ddraw surface. */
2394 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2395 if (parent)
2396 *value = parent->Handle;
2397 wined3d_texture_decref(tex);
2398 }
2399 wined3d_mutex_unlock();
2400
2401 return hr;
2402 }
2403
2404 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2405 {
2406 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2407 the mapping to get the value. */
2408 DWORD colorop, colorarg1, colorarg2;
2409 DWORD alphaop, alphaarg1, alphaarg2;
2410
2411 wined3d_mutex_lock();
2412
2413 device->legacyTextureBlending = TRUE;
2414
2415 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP, &colorop);
2416 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1, &colorarg1);
2417 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2, &colorarg2);
2418 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP, &alphaop);
2419 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1, &alphaarg1);
2420 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2, &alphaarg2);
2421
2422 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2423 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2424 *value = D3DTBLEND_DECAL;
2425 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2426 && alphaop == WINED3D_TOP_MODULATE
2427 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2428 *value = D3DTBLEND_DECALALPHA;
2429 else if (colorop == WINED3D_TOP_MODULATE
2430 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2431 && alphaop == WINED3D_TOP_MODULATE
2432 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2433 *value = D3DTBLEND_MODULATEALPHA;
2434 else
2435 {
2436 struct wined3d_texture *tex = NULL;
2437 HRESULT hr;
2438 BOOL tex_alpha = FALSE;
2439 DDPIXELFORMAT ddfmt;
2440
2441 hr = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
2442
2443 if(hr == WINED3D_OK && tex)
2444 {
2445 struct wined3d_resource *sub_resource;
2446
2447 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2448 {
2449 struct wined3d_resource_desc desc;
2450
2451 wined3d_resource_get_desc(sub_resource, &desc);
2452 ddfmt.dwSize = sizeof(ddfmt);
2453 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2454 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2455 }
2456
2457 wined3d_texture_decref(tex);
2458 }
2459
2460 if (!(colorop == WINED3D_TOP_MODULATE
2461 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2462 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2463 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2464 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2465
2466 *value = D3DTBLEND_MODULATE;
2467 }
2468
2469 wined3d_mutex_unlock();
2470
2471 return D3D_OK;
2472 }
2473
2474 default:
2475 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2476 }
2477 }
2478
2479 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2480 D3DRENDERSTATETYPE state, DWORD *value)
2481 {
2482 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2483
2484 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2485
2486 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2487 }
2488
2489 /*****************************************************************************
2490 * IDirect3DDevice7::SetRenderState
2491 *
2492 * Sets a render state. The possible render states are defined in
2493 * include/d3dtypes.h
2494 *
2495 * Version 2, 3 and 7
2496 *
2497 * Params:
2498 * RenderStateType: State to set
2499 * Value: Value to assign to that state
2500 *
2501 * Returns:
2502 * D3D_OK on success,
2503 * for details see IWineD3DDevice::SetRenderState
2504 *
2505 *****************************************************************************/
2506 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2507 D3DRENDERSTATETYPE state, DWORD value)
2508 {
2509 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2510 HRESULT hr;
2511
2512 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2513
2514 wined3d_mutex_lock();
2515 /* Some render states need special care */
2516 switch (state)
2517 {
2518 /*
2519 * The ddraw texture filter mapping works like this:
2520 * D3DFILTER_NEAREST Point min/mag, no mip
2521 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2522 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2523 *
2524 * D3DFILTER_LINEAR Linear min/mag, no mip
2525 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2526 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2527 *
2528 * This is the opposite of the GL naming convention,
2529 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2530 */
2531 case D3DRENDERSTATE_TEXTUREMAG:
2532 {
2533 enum wined3d_texture_filter_type tex_mag;
2534
2535 switch (value)
2536 {
2537 case D3DFILTER_NEAREST:
2538 case D3DFILTER_MIPNEAREST:
2539 case D3DFILTER_LINEARMIPNEAREST:
2540 tex_mag = WINED3D_TEXF_POINT;
2541 break;
2542 case D3DFILTER_LINEAR:
2543 case D3DFILTER_MIPLINEAR:
2544 case D3DFILTER_LINEARMIPLINEAR:
2545 tex_mag = WINED3D_TEXF_LINEAR;
2546 break;
2547 default:
2548 tex_mag = WINED3D_TEXF_POINT;
2549 FIXME("Unhandled texture mag %#x.\n", value);
2550 break;
2551 }
2552
2553 hr = wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2554 break;
2555 }
2556
2557 case D3DRENDERSTATE_TEXTUREMIN:
2558 {
2559 enum wined3d_texture_filter_type tex_min;
2560 enum wined3d_texture_filter_type tex_mip;
2561
2562 switch (value)
2563 {
2564 case D3DFILTER_NEAREST:
2565 tex_min = WINED3D_TEXF_POINT;
2566 tex_mip = WINED3D_TEXF_NONE;
2567 break;
2568 case D3DFILTER_LINEAR:
2569 tex_min = WINED3D_TEXF_LINEAR;
2570 tex_mip = WINED3D_TEXF_NONE;
2571 break;
2572 case D3DFILTER_MIPNEAREST:
2573 tex_min = WINED3D_TEXF_POINT;
2574 tex_mip = WINED3D_TEXF_POINT;
2575 break;
2576 case D3DFILTER_MIPLINEAR:
2577 tex_min = WINED3D_TEXF_LINEAR;
2578 tex_mip = WINED3D_TEXF_POINT;
2579 break;
2580 case D3DFILTER_LINEARMIPNEAREST:
2581 tex_min = WINED3D_TEXF_POINT;
2582 tex_mip = WINED3D_TEXF_LINEAR;
2583 break;
2584 case D3DFILTER_LINEARMIPLINEAR:
2585 tex_min = WINED3D_TEXF_LINEAR;
2586 tex_mip = WINED3D_TEXF_LINEAR;
2587 break;
2588
2589 default:
2590 FIXME("Unhandled texture min %#x.\n",value);
2591 tex_min = WINED3D_TEXF_POINT;
2592 tex_mip = WINED3D_TEXF_NONE;
2593 break;
2594 }
2595
2596 wined3d_device_set_sampler_state(device->wined3d_device,
2597 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2598 hr = wined3d_device_set_sampler_state(device->wined3d_device,
2599 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2600 break;
2601 }
2602
2603 case D3DRENDERSTATE_TEXTUREADDRESS:
2604 wined3d_device_set_sampler_state(device->wined3d_device,
2605 0, WINED3D_SAMP_ADDRESS_V, value);
2606 /* Drop through */
2607 case D3DRENDERSTATE_TEXTUREADDRESSU:
2608 hr = wined3d_device_set_sampler_state(device->wined3d_device,
2609 0, WINED3D_SAMP_ADDRESS_U, value);
2610 break;
2611 case D3DRENDERSTATE_TEXTUREADDRESSV:
2612 hr = wined3d_device_set_sampler_state(device->wined3d_device,
2613 0, WINED3D_SAMP_ADDRESS_V, value);
2614 break;
2615
2616 case D3DRENDERSTATE_BORDERCOLOR:
2617 /* This should probably just forward to the corresponding sampler
2618 * state. Needs tests. */
2619 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2620 hr = E_NOTIMPL;
2621 break;
2622
2623 case D3DRENDERSTATE_TEXTUREHANDLE:
2624 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2625 WARN("Render state %#x is invalid in d3d7.\n", state);
2626 hr = DDERR_INVALIDPARAMS;
2627 break;
2628
2629 case D3DRENDERSTATE_ZBIAS:
2630 hr = wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2631 break;
2632
2633 default:
2634 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2635 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2636 {
2637 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2638 hr = E_NOTIMPL;
2639 break;
2640 }
2641
2642 hr = wined3d_device_set_render_state(device->wined3d_device, state, value);
2643 break;
2644 }
2645 wined3d_mutex_unlock();
2646
2647 return hr;
2648 }
2649
2650 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2651 D3DRENDERSTATETYPE state, DWORD value)
2652 {
2653 return d3d_device7_SetRenderState(iface, state, value);
2654 }
2655
2656 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2657 D3DRENDERSTATETYPE state, DWORD value)
2658 {
2659 HRESULT hr;
2660 WORD old_fpucw;
2661
2662 old_fpucw = d3d_fpu_setup();
2663 hr = d3d_device7_SetRenderState(iface, state, value);
2664 set_fpu_control_word(old_fpucw);
2665
2666 return hr;
2667 }
2668
2669 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2670 D3DRENDERSTATETYPE state, DWORD value)
2671 {
2672 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2673 for this state can be directly mapped to texture stage colorop and alphaop, but
2674 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2675 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2676 alphaarg when needed.
2677
2678 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2679
2680 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2681 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2682 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2683 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2684 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2685 in device - TRUE if the app is using TEXTUREMAPBLEND.
2686
2687 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2688 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2689 unless some broken game will be found that cares. */
2690
2691 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2692 HRESULT hr;
2693
2694 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2695
2696 wined3d_mutex_lock();
2697
2698 switch (state)
2699 {
2700 case D3DRENDERSTATE_TEXTUREHANDLE:
2701 {
2702 struct ddraw_surface *surf;
2703
2704 if (value == 0)
2705 {
2706 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2707 break;
2708 }
2709
2710 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2711 if (!surf)
2712 {
2713 WARN("Invalid texture handle.\n");
2714 hr = DDERR_INVALIDPARAMS;
2715 break;
2716 }
2717
2718 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2719 break;
2720 }
2721
2722 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2723 {
2724 device->legacyTextureBlending = TRUE;
2725
2726 switch (value)
2727 {
2728 case D3DTBLEND_MODULATE:
2729 {
2730 struct wined3d_texture *tex = NULL;
2731 BOOL tex_alpha = FALSE;
2732 DDPIXELFORMAT ddfmt;
2733
2734 hr = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
2735
2736 if(hr == WINED3D_OK && tex)
2737 {
2738 struct wined3d_resource *sub_resource;
2739
2740 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2741 {
2742 struct wined3d_resource_desc desc;
2743
2744 wined3d_resource_get_desc(sub_resource, &desc);
2745 ddfmt.dwSize = sizeof(ddfmt);
2746 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2747 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2748 }
2749
2750 wined3d_texture_decref(tex);
2751 }
2752
2753 if (tex_alpha)
2754 wined3d_device_set_texture_stage_state(device->wined3d_device,
2755 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2756 else
2757 wined3d_device_set_texture_stage_state(device->wined3d_device,
2758 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2759 wined3d_device_set_texture_stage_state(device->wined3d_device,
2760 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2761 wined3d_device_set_texture_stage_state(device->wined3d_device,
2762 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2763 wined3d_device_set_texture_stage_state(device->wined3d_device,
2764 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2765 wined3d_device_set_texture_stage_state(device->wined3d_device,
2766 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2767 wined3d_device_set_texture_stage_state(device->wined3d_device,
2768 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2769 break;
2770 }
2771
2772 case D3DTBLEND_ADD:
2773 wined3d_device_set_texture_stage_state(device->wined3d_device,
2774 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2775 wined3d_device_set_texture_stage_state(device->wined3d_device,
2776 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2777 wined3d_device_set_texture_stage_state(device->wined3d_device,
2778 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2779 wined3d_device_set_texture_stage_state(device->wined3d_device,
2780 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2781 wined3d_device_set_texture_stage_state(device->wined3d_device,
2782 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2783 break;
2784
2785 case D3DTBLEND_MODULATEALPHA:
2786 wined3d_device_set_texture_stage_state(device->wined3d_device,
2787 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2788 wined3d_device_set_texture_stage_state(device->wined3d_device,
2789 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2790 wined3d_device_set_texture_stage_state(device->wined3d_device,
2791 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2792 wined3d_device_set_texture_stage_state(device->wined3d_device,
2793 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2794 wined3d_device_set_texture_stage_state(device->wined3d_device,
2795 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2796 wined3d_device_set_texture_stage_state(device->wined3d_device,
2797 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2798 break;
2799
2800 case D3DTBLEND_COPY:
2801 case D3DTBLEND_DECAL:
2802 wined3d_device_set_texture_stage_state(device->wined3d_device,
2803 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2804 wined3d_device_set_texture_stage_state(device->wined3d_device,
2805 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2806 wined3d_device_set_texture_stage_state(device->wined3d_device,
2807 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2808 wined3d_device_set_texture_stage_state(device->wined3d_device,
2809 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2810 break;
2811
2812 case D3DTBLEND_DECALALPHA:
2813 wined3d_device_set_texture_stage_state(device->wined3d_device,
2814 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2815 wined3d_device_set_texture_stage_state(device->wined3d_device,
2816 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2817 wined3d_device_set_texture_stage_state(device->wined3d_device,
2818 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2819 wined3d_device_set_texture_stage_state(device->wined3d_device,
2820 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2821 wined3d_device_set_texture_stage_state(device->wined3d_device,
2822 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2823 break;
2824
2825 default:
2826 FIXME("Unhandled texture environment %#x.\n", value);
2827 }
2828
2829 hr = D3D_OK;
2830 break;
2831 }
2832
2833 default:
2834 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2835 break;
2836 }
2837 wined3d_mutex_unlock();
2838
2839 return hr;
2840 }
2841
2842 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2843 D3DRENDERSTATETYPE state, DWORD value)
2844 {
2845 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2846
2847 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2848
2849 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2850 }
2851
2852 /*****************************************************************************
2853 * Direct3DDevice3::SetLightState
2854 *
2855 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2856 * light states are forwarded to Direct3DDevice7 render states
2857 *
2858 * Version 2 and 3
2859 *
2860 * Params:
2861 * LightStateType: The light state to change
2862 * Value: The value to assign to that light state
2863 *
2864 * Returns:
2865 * D3D_OK on success
2866 * DDERR_INVALIDPARAMS if the parameters were incorrect
2867 * Also check IDirect3DDevice7::SetRenderState
2868 *
2869 *****************************************************************************/
2870 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2871 D3DLIGHTSTATETYPE state, DWORD value)
2872 {
2873 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2874 HRESULT hr;
2875
2876 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2877
2878 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2879 {
2880 TRACE("Unexpected Light State Type\n");
2881 return DDERR_INVALIDPARAMS;
2882 }
2883
2884 wined3d_mutex_lock();
2885 if (state == D3DLIGHTSTATE_MATERIAL)
2886 {
2887 struct d3d_material *m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL);
2888 if (!m)
2889 {
2890 WARN("Invalid material handle.\n");
2891 wined3d_mutex_unlock();
2892 return DDERR_INVALIDPARAMS;
2893 }
2894
2895 TRACE(" activating material %p.\n", m);
2896 material_activate(m);
2897
2898 device->material = value;
2899 }
2900 else if (state == D3DLIGHTSTATE_COLORMODEL)
2901 {
2902 switch (value)
2903 {
2904 case D3DCOLOR_MONO:
2905 ERR("DDCOLOR_MONO should not happen!\n");
2906 break;
2907 case D3DCOLOR_RGB:
2908 /* We are already in this mode */
2909 TRACE("Setting color model to RGB (no-op).\n");
2910 break;
2911 default:
2912 ERR("Unknown color model!\n");
2913 wined3d_mutex_unlock();
2914 return DDERR_INVALIDPARAMS;
2915 }
2916 }
2917 else
2918 {
2919 D3DRENDERSTATETYPE rs;
2920 switch (state)
2921 {
2922 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2923 rs = D3DRENDERSTATE_AMBIENT;
2924 break;
2925 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2926 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2927 break;
2928 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2929 rs = D3DRENDERSTATE_FOGSTART;
2930 break;
2931 case D3DLIGHTSTATE_FOGEND: /* 6 */
2932 rs = D3DRENDERSTATE_FOGEND;
2933 break;
2934 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2935 rs = D3DRENDERSTATE_FOGDENSITY;
2936 break;
2937 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2938 rs = D3DRENDERSTATE_COLORVERTEX;
2939 break;
2940 default:
2941 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2942 wined3d_mutex_unlock();
2943 return DDERR_INVALIDPARAMS;
2944 }
2945
2946 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2947 wined3d_mutex_unlock();
2948 return hr;
2949 }
2950 wined3d_mutex_unlock();
2951
2952 return D3D_OK;
2953 }
2954
2955 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
2956 D3DLIGHTSTATETYPE state, DWORD value)
2957 {
2958 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2959
2960 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2961
2962 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
2963 }
2964
2965 /*****************************************************************************
2966 * IDirect3DDevice3::GetLightState
2967 *
2968 * Returns the current setting of a light state. The state is read from
2969 * the Direct3DDevice7 render state.
2970 *
2971 * Version 2 and 3
2972 *
2973 * Params:
2974 * LightStateType: The light state to return
2975 * Value: The address to store the light state setting at
2976 *
2977 * Returns:
2978 * D3D_OK on success
2979 * DDDERR_INVALIDPARAMS if the parameters were incorrect
2980 * Also see IDirect3DDevice7::GetRenderState
2981 *
2982 *****************************************************************************/
2983 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
2984 D3DLIGHTSTATETYPE state, DWORD *value)
2985 {
2986 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2987 HRESULT hr;
2988
2989 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2990
2991 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2992 {
2993 TRACE("Unexpected Light State Type\n");
2994 return DDERR_INVALIDPARAMS;
2995 }
2996
2997 if (!value)
2998 return DDERR_INVALIDPARAMS;
2999
3000 wined3d_mutex_lock();
3001 if (state == D3DLIGHTSTATE_MATERIAL)
3002 {
3003 *value = device->material;
3004 }
3005 else if (state == D3DLIGHTSTATE_COLORMODEL)
3006 {
3007 *value = D3DCOLOR_RGB;
3008 }
3009 else
3010 {
3011 D3DRENDERSTATETYPE rs;
3012 switch (state)
3013 {
3014 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3015 rs = D3DRENDERSTATE_AMBIENT;
3016 break;
3017 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3018 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3019 break;
3020 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3021 rs = D3DRENDERSTATE_FOGSTART;
3022 break;
3023 case D3DLIGHTSTATE_FOGEND: /* 6 */
3024 rs = D3DRENDERSTATE_FOGEND;
3025 break;
3026 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3027 rs = D3DRENDERSTATE_FOGDENSITY;
3028 break;
3029 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3030 rs = D3DRENDERSTATE_COLORVERTEX;
3031 break;
3032 default:
3033 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3034 wined3d_mutex_unlock();
3035 return DDERR_INVALIDPARAMS;
3036 }
3037
3038 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3039 wined3d_mutex_unlock();
3040 return hr;
3041 }
3042 wined3d_mutex_unlock();
3043
3044 return D3D_OK;
3045 }
3046
3047 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3048 D3DLIGHTSTATETYPE state, DWORD *value)
3049 {
3050 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3051
3052 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3053
3054 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3055 }
3056
3057 /*****************************************************************************
3058 * IDirect3DDevice7::SetTransform
3059 *
3060 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3061 * in include/d3dtypes.h.
3062 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3063 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3064 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3065 *
3066 * Version 2, 3 and 7
3067 *
3068 * Params:
3069 * TransformStateType: transform state to set
3070 * Matrix: Matrix to assign to the state
3071 *
3072 * Returns:
3073 * D3D_OK on success
3074 * DDERR_INVALIDPARAMS if Matrix == NULL
3075 * For details see IWineD3DDevice::SetTransform
3076 *
3077 *****************************************************************************/
3078 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3079 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3080 {
3081 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3082 enum wined3d_transform_state wined3d_state;
3083 HRESULT hr;
3084
3085 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3086
3087 switch (state)
3088 {
3089 case D3DTRANSFORMSTATE_WORLD:
3090 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3091 break;
3092 case D3DTRANSFORMSTATE_WORLD1:
3093 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3094 break;
3095 case D3DTRANSFORMSTATE_WORLD2:
3096 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3097 break;
3098 case D3DTRANSFORMSTATE_WORLD3:
3099 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3100 break;
3101 default:
3102 wined3d_state = state;
3103 }
3104
3105 if (!matrix)
3106 return DDERR_INVALIDPARAMS;
3107
3108 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3109 wined3d_mutex_lock();
3110 hr = wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3111 wined3d_mutex_unlock();
3112
3113 return hr;
3114 }
3115
3116 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3117 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3118 {
3119 return d3d_device7_SetTransform(iface, state, matrix);
3120 }
3121
3122 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3123 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3124 {
3125 HRESULT hr;
3126 WORD old_fpucw;
3127
3128 old_fpucw = d3d_fpu_setup();
3129 hr = d3d_device7_SetTransform(iface, state, matrix);
3130 set_fpu_control_word(old_fpucw);
3131
3132 return hr;
3133 }
3134
3135 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3136 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3137 {
3138 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3139
3140 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3141
3142 if (!matrix)
3143 return DDERR_INVALIDPARAMS;
3144
3145 if (state == D3DTRANSFORMSTATE_PROJECTION)
3146 {
3147 D3DMATRIX projection;
3148 HRESULT hr;
3149
3150 wined3d_mutex_lock();
3151 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3152 hr = wined3d_device_set_transform(device->wined3d_device,
3153 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3154 if (SUCCEEDED(hr))
3155 device->legacy_projection = *matrix;
3156 wined3d_mutex_unlock();
3157
3158 return hr;
3159 }
3160
3161 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3162 }
3163
3164 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3165 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3166 {
3167 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3168
3169 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3170
3171 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3172 }
3173
3174 /*****************************************************************************
3175 * IDirect3DDevice7::GetTransform
3176 *
3177 * Returns the matrix assigned to a transform state
3178 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3179 * SetTransform
3180 *
3181 * Params:
3182 * TransformStateType: State to read the matrix from
3183 * Matrix: Address to store the matrix at
3184 *
3185 * Returns:
3186 * D3D_OK on success
3187 * DDERR_INVALIDPARAMS if Matrix == NULL
3188 * For details, see IWineD3DDevice::GetTransform
3189 *
3190 *****************************************************************************/
3191 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3192 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3193 {
3194 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3195 enum wined3d_transform_state wined3d_state;
3196 HRESULT hr;
3197
3198 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3199
3200 switch (state)
3201 {
3202 case D3DTRANSFORMSTATE_WORLD:
3203 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3204 break;
3205 case D3DTRANSFORMSTATE_WORLD1:
3206 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3207 break;
3208 case D3DTRANSFORMSTATE_WORLD2:
3209 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3210 break;
3211 case D3DTRANSFORMSTATE_WORLD3:
3212 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3213 break;
3214 default:
3215 wined3d_state = state;
3216 }
3217
3218 if (!matrix)
3219 return DDERR_INVALIDPARAMS;
3220
3221 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3222 wined3d_mutex_lock();
3223 hr = wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3224 wined3d_mutex_unlock();
3225
3226 return hr;
3227 }
3228
3229 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3230 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3231 {
3232 return d3d_device7_GetTransform(iface, state, matrix);
3233 }
3234
3235 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3236 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3237 {
3238 HRESULT hr;
3239 WORD old_fpucw;
3240
3241 old_fpucw = d3d_fpu_setup();
3242 hr = d3d_device7_GetTransform(iface, state, matrix);
3243 set_fpu_control_word(old_fpucw);
3244
3245 return hr;
3246 }
3247
3248 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3249 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3250 {
3251 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3252
3253 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3254
3255 if (!matrix)
3256 return DDERR_INVALIDPARAMS;
3257
3258 if (state == D3DTRANSFORMSTATE_PROJECTION)
3259 {
3260 wined3d_mutex_lock();
3261 *matrix = device->legacy_projection;
3262 wined3d_mutex_unlock();
3263 return DD_OK;
3264 }
3265
3266 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3267 }
3268
3269 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3270 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3271 {
3272 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3273
3274 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3275
3276 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3277 }
3278
3279 /*****************************************************************************
3280 * IDirect3DDevice7::MultiplyTransform
3281 *
3282 * Multiplies the already-set transform matrix of a transform state
3283 * with another matrix. For the world matrix, see SetTransform
3284 *
3285 * Version 2, 3 and 7
3286 *
3287 * Params:
3288 * TransformStateType: Transform state to multiply
3289 * D3DMatrix Matrix to multiply with.
3290 *
3291 * Returns
3292 * D3D_OK on success
3293 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3294 * For details, see IWineD3DDevice::MultiplyTransform
3295 *
3296 *****************************************************************************/
3297 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3298 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3299 {
3300 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3301 enum wined3d_transform_state wined3d_state;
3302 HRESULT hr;
3303
3304 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3305
3306 switch (state)
3307 {
3308 case D3DTRANSFORMSTATE_WORLD:
3309 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3310 break;
3311 case D3DTRANSFORMSTATE_WORLD1:
3312 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3313 break;
3314 case D3DTRANSFORMSTATE_WORLD2:
3315 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3316 break;
3317 case D3DTRANSFORMSTATE_WORLD3:
3318 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3319 break;
3320 default:
3321 wined3d_state = state;
3322 }
3323
3324 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3325 wined3d_mutex_lock();
3326 hr = wined3d_device_multiply_transform(device->wined3d_device,
3327 wined3d_state, (struct wined3d_matrix *)matrix);
3328 wined3d_mutex_unlock();
3329
3330 return hr;
3331 }
3332
3333 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3334 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3335 {
3336 return d3d_device7_MultiplyTransform(iface, state, matrix);
3337 }
3338
3339 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3340 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3341 {
3342 HRESULT hr;
3343 WORD old_fpucw;
3344
3345 old_fpucw = d3d_fpu_setup();
3346 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3347 set_fpu_control_word(old_fpucw);
3348
3349 return hr;
3350 }
3351
3352 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3353 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3354 {
3355 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3356
3357 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3358
3359 if (state == D3DTRANSFORMSTATE_PROJECTION)
3360 {
3361 D3DMATRIX projection, tmp;
3362 HRESULT hr;
3363
3364 wined3d_mutex_lock();
3365 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3366 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3367 hr = wined3d_device_set_transform(device->wined3d_device,
3368 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3369 if (SUCCEEDED(hr))
3370 device->legacy_projection = tmp;
3371 wined3d_mutex_unlock();
3372
3373 return hr;
3374 }
3375
3376 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3377 }
3378
3379 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3380 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3381 {
3382 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3383
3384 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3385
3386 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3387 }
3388
3389 /*****************************************************************************
3390 * IDirect3DDevice7::DrawPrimitive
3391 *
3392 * Draws primitives based on vertices in an application-provided pointer
3393 *
3394 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3395 * an FVF format for D3D7
3396 *
3397 * Params:
3398 * PrimitiveType: The type of the primitives to draw
3399 * Vertex type: Flexible vertex format vertex description
3400 * Vertices: Pointer to the vertex array
3401 * VertexCount: The number of vertices to draw
3402 * Flags: As usual a few flags
3403 *
3404 * Returns:
3405 * D3D_OK on success
3406 * DDERR_INVALIDPARAMS if Vertices is NULL
3407 * For details, see IWineD3DDevice::DrawPrimitiveUP
3408 *
3409 *****************************************************************************/
3410 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3411 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3412 DWORD vertex_count, DWORD flags)
3413 {
3414 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3415 UINT stride;
3416 HRESULT hr;
3417
3418 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3419 iface, primitive_type, fvf, vertices, vertex_count, flags);
3420
3421 if (!vertices)
3422 return DDERR_INVALIDPARAMS;
3423
3424 /* Get the stride */
3425 stride = get_flexible_vertex_size(fvf);
3426
3427 /* Set the FVF */
3428 wined3d_mutex_lock();
3429 hr = wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3430 if (hr != D3D_OK)
3431 {
3432 wined3d_mutex_unlock();
3433 return hr;
3434 }
3435
3436 /* This method translates to the user pointer draw of WineD3D */
3437 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3438 hr = wined3d_device_draw_primitive_up(device->wined3d_device, vertex_count, vertices, stride);
3439 wined3d_mutex_unlock();
3440
3441 return hr;
3442 }
3443
3444 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3445 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3446 DWORD vertex_count, DWORD flags)
3447 {
3448 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3449 }
3450
3451 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3452 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3453 DWORD vertex_count, DWORD flags)
3454 {
3455 HRESULT hr;
3456 WORD old_fpucw;
3457
3458 old_fpucw = d3d_fpu_setup();
3459 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3460 set_fpu_control_word(old_fpucw);
3461
3462 return hr;
3463 }
3464
3465 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3466 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3467 DWORD flags)
3468 {
3469 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3470
3471 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3472 iface, primitive_type, fvf, vertices, vertex_count, flags);
3473
3474 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3475 primitive_type, fvf, vertices, vertex_count, flags);
3476 }
3477
3478 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3479 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3480 DWORD vertex_count, DWORD flags)
3481 {
3482 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3483 DWORD fvf;
3484
3485 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3486 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3487
3488 switch (vertex_type)
3489 {
3490 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3491 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3492 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3493 default:
3494 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3495 return DDERR_INVALIDPARAMS; /* Should never happen */
3496 }
3497
3498 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3499 primitive_type, fvf, vertices, vertex_count, flags);
3500 }
3501
3502 /*****************************************************************************
3503 * IDirect3DDevice7::DrawIndexedPrimitive
3504 *
3505 * Draws vertices from an application-provided pointer, based on the index
3506 * numbers in a WORD array.
3507 *
3508 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3509 * an FVF format for D3D7
3510 *
3511 * Params:
3512 * PrimitiveType: The primitive type to draw
3513 * VertexType: The FVF vertex description
3514 * Vertices: Pointer to the vertex array
3515 * VertexCount: ?
3516 * Indices: Pointer to the index array
3517 * IndexCount: Number of indices = Number of vertices to draw
3518 * Flags: As usual, some flags
3519 *
3520 * Returns:
3521 * D3D_OK on success
3522 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3523 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3524 *
3525 *****************************************************************************/
3526 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3527 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3528 WORD *indices, DWORD index_count, DWORD flags)
3529 {
3530 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3531 HRESULT hr;
3532
3533 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3534 "indices %p, index_count %u, flags %#x.\n",
3535 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3536
3537 /* Set the D3DDevice's FVF */
3538 wined3d_mutex_lock();
3539 hr = wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3540 if (FAILED(hr))
3541 {
3542 WARN("Failed to set vertex declaration, hr %#x.\n", hr);
3543 wined3d_mutex_unlock();
3544 return hr;
3545 }
3546
3547 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3548 hr = wined3d_device_draw_indexed_primitive_up(device->wined3d_device, index_count, indices,
3549 WINED3DFMT_R16_UINT, vertices, get_flexible_vertex_size(fvf));
3550 wined3d_mutex_unlock();
3551
3552 return hr;
3553 }
3554
3555 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3556 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3557 WORD *indices, DWORD index_count, DWORD flags)
3558 {
3559 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3560 vertices, vertex_count, indices, index_count, flags);
3561 }
3562
3563 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3564 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3565 WORD *indices, DWORD index_count, DWORD flags)
3566 {
3567 HRESULT hr;
3568 WORD old_fpucw;
3569
3570 old_fpucw = d3d_fpu_setup();
3571 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3572 vertices, vertex_count, indices, index_count, flags);
3573 set_fpu_control_word(old_fpucw);
3574
3575 return hr;
3576 }
3577
3578 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3579 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3580 WORD *indices, DWORD index_count, DWORD flags)
3581 {
3582 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3583
3584 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3585 "indices %p, index_count %u, flags %#x.\n",
3586 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3587
3588 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3589 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3590 }
3591
3592 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3593 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3594 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3595 {
3596 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3597 DWORD fvf;
3598
3599 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3600 "indices %p, index_count %u, flags %#x.\n",
3601 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3602
3603 switch (vertex_type)
3604 {
3605 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3606 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3607 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3608 default:
3609 ERR("Unhandled vertex type %#x.\n", vertex_type);
3610 return DDERR_INVALIDPARAMS; /* Should never happen */
3611 }
3612
3613 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3614 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3615 }
3616
3617 /*****************************************************************************
3618 * IDirect3DDevice7::SetClipStatus
3619 *
3620 * Sets the clip status. This defines things as clipping conditions and
3621 * the extents of the clipping region.
3622 *
3623 * Version 2, 3 and 7
3624 *
3625 * Params:
3626 * ClipStatus:
3627 *
3628 * Returns:
3629 * D3D_OK because it's a stub
3630 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3631 *
3632 *****************************************************************************/
3633 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3634 {
3635 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3636
3637 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3638 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3639 */
3640 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3641 return D3D_OK;
3642 }
3643
3644 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3645 {
3646 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3647
3648 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3649
3650 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3651 }
3652
3653 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3654 {
3655 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3656
3657 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3658
3659 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3660 }
3661
3662 /*****************************************************************************
3663 * IDirect3DDevice7::GetClipStatus
3664 *
3665 * Returns the clip status
3666 *
3667 * Params:
3668 * ClipStatus: Address to write the clip status to
3669 *
3670 * Returns:
3671 * D3D_OK because it's a stub
3672 *
3673 *****************************************************************************/
3674 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3675 {
3676 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3677
3678 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3679 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3680 return D3D_OK;
3681 }
3682
3683 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3684 {
3685 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3686
3687 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3688
3689 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3690 }
3691
3692 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3693 {
3694 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3695
3696 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3697
3698 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3699 }
3700
3701 /*****************************************************************************
3702 * IDirect3DDevice::DrawPrimitiveStrided
3703 *
3704 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3705 *
3706 * Version 3 and 7
3707 *
3708 * Params:
3709 * PrimitiveType: The primitive type to draw
3710 * VertexType: The FVF description of the vertices to draw (for the stride??)
3711 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3712 * the vertex data locations
3713 * VertexCount: The number of vertices to draw
3714 * Flags: Some flags
3715 *
3716 * Returns:
3717 * D3D_OK, because it's a stub
3718 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3719 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3720 *
3721 *****************************************************************************/
3722 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3723 DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3724 {
3725 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3726 struct wined3d_strided_data wined3d_strided;
3727 DWORD i;
3728 HRESULT hr;
3729
3730 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3731 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3732
3733 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3734 /* Get the strided data right. the wined3d structure is a bit bigger
3735 * Watch out: The contents of the strided data are determined by the fvf,
3736 * not by the members set in D3DDrawPrimStrideData. So it's valid
3737 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3738 * not set in the fvf.
3739 */
3740 if(VertexType & D3DFVF_POSITION_MASK)
3741 {
3742 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3743 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3744 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3745 if (VertexType & D3DFVF_XYZRHW)
3746 {
3747 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3748 wined3d_strided.position_transformed = TRUE;
3749 }
3750 else
3751 {
3752 wined3d_strided.position_transformed = FALSE;
3753 }
3754 }
3755
3756 if (VertexType & D3DFVF_NORMAL)
3757 {
3758 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3759 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3760 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3761 }
3762
3763 if (VertexType & D3DFVF_DIFFUSE)
3764 {
3765 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3766 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3767 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3768 }
3769
3770 if (VertexType & D3DFVF_SPECULAR)
3771 {
3772 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3773 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3774 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3775 }
3776
3777 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3778 {
3779 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3780 {
3781 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3782 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3783 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3784 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3785 default: ERR("Unexpected texture coordinate size %d\n",
3786 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3787 }
3788 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3789 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3790 }
3791
3792 /* WineD3D doesn't need the FVF here */
3793 wined3d_mutex_lock();
3794 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3795 hr = wined3d_device_draw_primitive_strided(device->wined3d_device, VertexCount, &wined3d_strided);
3796 wined3d_mutex_unlock();
3797
3798 return hr;
3799 }
3800
3801 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3802 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3803 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3804 {
3805 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3806 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3807 }
3808
3809 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3810 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3811 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3812 {
3813 HRESULT hr;
3814 WORD old_fpucw;
3815
3816 old_fpucw = d3d_fpu_setup();
3817 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3818 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3819 set_fpu_control_word(old_fpucw);
3820
3821 return hr;
3822 }
3823
3824 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3825 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3826 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3827 {
3828 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3829
3830 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3831 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3832
3833 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
3834 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3835 }
3836
3837 /*****************************************************************************
3838 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3839 *
3840 * Draws primitives specified by strided data locations based on indices
3841 *
3842 * Version 3 and 7
3843 *
3844 * Params:
3845 * PrimitiveType:
3846 *
3847 * Returns:
3848 * D3D_OK, because it's a stub
3849 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3850 * (DDERR_INVALIDPARAMS if Indices is NULL)
3851 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3852 *
3853 *****************************************************************************/
3854 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3855 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3856 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3857 WORD *Indices, DWORD IndexCount, DWORD Flags)
3858 {
3859 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3860 struct wined3d_strided_data wined3d_strided;
3861 DWORD i;
3862 HRESULT hr;
3863
3864 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3865 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3866
3867 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3868 /* Get the strided data right. the wined3d structure is a bit bigger
3869 * Watch out: The contents of the strided data are determined by the fvf,
3870 * not by the members set in D3DDrawPrimStrideData. So it's valid
3871 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3872 * not set in the fvf. */
3873 if (VertexType & D3DFVF_POSITION_MASK)
3874 {
3875 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3876 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3877 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3878 if (VertexType & D3DFVF_XYZRHW)
3879 {
3880 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3881 wined3d_strided.position_transformed = TRUE;
3882 }
3883 else
3884 {
3885 wined3d_strided.position_transformed = FALSE;
3886 }
3887 }
3888
3889 if (VertexType & D3DFVF_NORMAL)
3890 {
3891 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3892 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3893 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3894 }
3895
3896 if (VertexType & D3DFVF_DIFFUSE)
3897 {
3898 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3899 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3900 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3901 }
3902
3903 if (VertexType & D3DFVF_SPECULAR)
3904 {
3905 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3906 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3907 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3908 }
3909
3910 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3911 {
3912 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3913 {
3914 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3915 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3916 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3917 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3918 default: ERR("Unexpected texture coordinate size %d\n",
3919 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3920 }
3921 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3922 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3923 }
3924
3925 /* WineD3D doesn't need the FVF here */
3926 wined3d_mutex_lock();
3927 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3928 hr = wined3d_device_draw_indexed_primitive_strided(device->wined3d_device,
3929 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3930 wined3d_mutex_unlock();
3931
3932 return hr;
3933 }
3934
3935 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3936 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3937 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3938 WORD *Indices, DWORD IndexCount, DWORD Flags)
3939 {
3940 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
3941 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3942 }
3943
3944 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3945 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3946 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3947 WORD *Indices, DWORD IndexCount, DWORD Flags)
3948 {
3949 HRESULT hr;
3950 WORD old_fpucw;
3951
3952 old_fpucw = d3d_fpu_setup();
3953 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
3954 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3955 set_fpu_control_word(old_fpucw);
3956
3957 return hr;
3958 }
3959
3960 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
3961 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3962 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
3963 DWORD IndexCount, DWORD Flags)
3964 {
3965 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3966
3967 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3968 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3969
3970 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
3971 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3972 }
3973
3974 /*****************************************************************************
3975 * IDirect3DDevice7::DrawPrimitiveVB
3976 *
3977 * Draws primitives from a vertex buffer to the screen.
3978 *
3979 * Version 3 and 7
3980 *
3981 * Params:
3982 * PrimitiveType: Type of primitive to be rendered.
3983 * D3DVertexBuf: Source Vertex Buffer
3984 * StartVertex: Index of the first vertex from the buffer to be rendered
3985 * NumVertices: Number of vertices to be rendered
3986 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
3987 *
3988 * Return values
3989 * D3D_OK on success
3990 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
3991 *
3992 *****************************************************************************/
3993 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3994 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
3995 {
3996 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3997 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
3998 HRESULT hr;
3999 DWORD stride;
4000
4001 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4002 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4003
4004 /* Sanity checks */
4005 if (!vb)
4006 {
4007 WARN("No Vertex buffer specified.\n");
4008 return DDERR_INVALIDPARAMS;
4009 }
4010 stride = get_flexible_vertex_size(vb->fvf);
4011
4012 wined3d_mutex_lock();
4013 hr = wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
4014 if (FAILED(hr))
4015 {
4016 WARN("Failed to set vertex declaration, hr %#x.\n", hr);
4017 wined3d_mutex_unlock();
4018 return hr;
4019 }
4020
4021 /* Set the vertex stream source */
4022 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4023 if (FAILED(hr))
4024 {
4025 WARN("Failed to set stream source, hr %#x.\n", hr);
4026 wined3d_mutex_unlock();
4027 return hr;
4028 }
4029
4030 /* Now draw the primitives */
4031 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4032 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
4033 wined3d_mutex_unlock();
4034
4035 return hr;
4036 }
4037
4038 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4039 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4040 {
4041 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4042 }
4043
4044 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4045 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4046 {
4047 HRESULT hr;
4048 WORD old_fpucw;
4049
4050 old_fpucw = d3d_fpu_setup();
4051 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4052 set_fpu_control_word(old_fpucw);
4053
4054 return hr;
4055 }
4056
4057 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4058 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4059 {
4060 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4061 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4062
4063 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4064 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4065
4066 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4067 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4068 }
4069
4070
4071 /*****************************************************************************
4072 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4073 *
4074 * Draws primitives from a vertex buffer to the screen
4075 *
4076 * Params:
4077 * PrimitiveType: Type of primitive to be rendered.
4078 * D3DVertexBuf: Source Vertex Buffer
4079 * StartVertex: Index of the first vertex from the buffer to be rendered
4080 * NumVertices: Number of vertices to be rendered
4081 * Indices: Array of DWORDs used to index into the Vertices
4082 * IndexCount: Number of indices in Indices
4083 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4084 *
4085 * Return values
4086 *
4087 *****************************************************************************/
4088 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4089 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4090 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4091 {
4092 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4093 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4094 DWORD stride = get_flexible_vertex_size(vb->fvf);
4095 struct wined3d_resource *wined3d_resource;
4096 struct wined3d_resource_desc desc;
4097 WORD *LockedIndices;
4098 HRESULT hr;
4099
4100 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4101 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4102
4103 /* Steps:
4104 * 1) Upload the Indices to the index buffer
4105 * 2) Set the index source
4106 * 3) Set the Vertex Buffer as the Stream source
4107 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4108 */
4109
4110 wined3d_mutex_lock();
4111
4112 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4113 if (FAILED(hr))
4114 {
4115 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4116 wined3d_mutex_unlock();
4117 return hr;
4118 }
4119
4120 /* check that the buffer is large enough to hold the indices,
4121 * reallocate if necessary. */
4122 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4123 wined3d_resource_get_desc(wined3d_resource, &desc);
4124 if (desc.size < IndexCount * sizeof(WORD))
4125 {
4126 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4127 struct wined3d_buffer *buffer;
4128
4129 TRACE("Growing index buffer to %u bytes\n", size);
4130
4131 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4132 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4133 if (FAILED(hr))
4134 {
4135 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4136 wined3d_mutex_unlock();
4137 return hr;
4138 }
4139
4140 wined3d_buffer_decref(This->indexbuffer);
4141 This->indexbuffer = buffer;
4142 }
4143
4144 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4145 * method could be created which takes an user pointer containing the
4146 * indices or a SetData-Method for the index buffer, which overrides the
4147 * index buffer data with our pointer. */
4148 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4149 (BYTE **)&LockedIndices, 0);
4150 if (FAILED(hr))
4151 {
4152 ERR("Failed to map buffer, hr %#x.\n", hr);
4153 wined3d_mutex_unlock();
4154 return hr;
4155 }
4156 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4157 wined3d_buffer_unmap(This->indexbuffer);
4158
4159 /* Set the index stream */
4160 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4161 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4162
4163 /* Set the vertex stream source */
4164 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4165 if (FAILED(hr))
4166 {
4167 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4168 wined3d_mutex_unlock();
4169 return hr;
4170 }
4171
4172
4173 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4174 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4175
4176 wined3d_mutex_unlock();
4177
4178 return hr;
4179 }
4180
4181 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4182 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4183 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4184 {
4185 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4186 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4187 }
4188
4189 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4190 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4191 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4192 {
4193 HRESULT hr;
4194 WORD old_fpucw;
4195
4196 old_fpucw = d3d_fpu_setup();
4197 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4198 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4199 set_fpu_control_word(old_fpucw);
4200
4201 return hr;
4202 }
4203
4204 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4205 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4206 DWORD IndexCount, DWORD Flags)
4207 {
4208 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4209 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4210
4211 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4212 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4213
4214 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4215 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4216 }
4217
4218 /*****************************************************************************
4219 * IDirect3DDevice7::ComputeSphereVisibility
4220 *
4221 * Calculates the visibility of spheres in the current viewport. The spheres
4222 * are passed in the Centers and Radii arrays, the results are passed back
4223 * in the ReturnValues array. Return values are either completely visible,
4224 * partially visible or completely invisible.
4225 * The return value consist of a combination of D3DCLIP_* flags, or it's
4226 * 0 if the sphere is completely visible(according to the SDK, not checked)
4227 *
4228 * Version 3 and 7
4229 *
4230 * Params:
4231 * Centers: Array containing the sphere centers
4232 * Radii: Array containing the sphere radii
4233 * NumSpheres: The number of centers and radii in the arrays
4234 * Flags: Some flags
4235 * ReturnValues: Array to write the results to
4236 *
4237 * Returns:
4238 * D3D_OK
4239 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4240 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4241 * is singular)
4242 *
4243 *****************************************************************************/
4244
4245 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4246 {
4247 float distance, norm;
4248
4249 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4250 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4251
4252 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4253 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4254 return 0;
4255 }
4256
4257 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4258 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4259 {
4260 D3DMATRIX m, temp;
4261 D3DVALUE origin_plane[6];
4262 D3DVECTOR vec[6];
4263 HRESULT hr;
4264 UINT i, j;
4265
4266 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4267 iface, centers, radii, sphere_count, flags, return_values);
4268
4269 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4270 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4271 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4272 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4273 multiply_matrix(&m, &temp, &m);
4274
4275 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4276 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4277 multiply_matrix(&m, &temp, &m);
4278
4279 /* Left plane */
4280 vec[0].u1.x = m._14 + m._11;
4281 vec[0].u2.y = m._24 + m._21;
4282 vec[0].u3.z = m._34 + m._31;
4283 origin_plane[0] = m._44 + m._41;
4284
4285 /* Right plane */
4286 vec[1].u1.x = m._14 - m._11;
4287 vec[1].u2.y = m._24 - m._21;
4288 vec[1].u3.z = m._34 - m._31;
4289 origin_plane[1] = m._44 - m._41;
4290
4291 /* Top plane */
4292 vec[2].u1.x = m._14 - m._12;
4293 vec[2].u2.y = m._24 - m._22;
4294 vec[2].u3.z = m._34 - m._32;
4295 origin_plane[2] = m._44 - m._42;
4296
4297 /* Bottom plane */
4298 vec[3].u1.x = m._14 + m._12;
4299 vec[3].u2.y = m._24 + m._22;
4300 vec[3].u3.z = m._34 + m._32;
4301 origin_plane[3] = m._44 + m._42;
4302
4303 /* Front plane */
4304 vec[4].u1.x = m._13;
4305 vec[4].u2.y = m._23;
4306 vec[4].u3.z = m._33;
4307 origin_plane[4] = m._43;
4308
4309 /* Back plane*/
4310 vec[5].u1.x = m._14 - m._13;
4311 vec[5].u2.y = m._24 - m._23;
4312 vec[5].u3.z = m._34 - m._33;
4313 origin_plane[5] = m._44 - m._43;
4314
4315 for (i = 0; i < sphere_count; ++i)
4316 {
4317 return_values[i] = 0;
4318 for (j = 0; j < 6; ++j)
4319 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4320 }
4321
4322 return D3D_OK;
4323 }
4324
4325 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4326 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4327 {
4328 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4329
4330 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4331 iface, centers, radii, sphere_count, flags, return_values);
4332
4333 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4334 centers, radii, sphere_count, flags, return_values);
4335 }
4336
4337 /*****************************************************************************
4338 * IDirect3DDevice7::GetTexture
4339 *
4340 * Returns the texture interface handle assigned to a texture stage.
4341 * The returned texture is AddRefed. This is taken from old ddraw,
4342 * not checked in Windows.
4343 *
4344 * Version 3 and 7
4345 *
4346 * Params:
4347 * Stage: Texture stage to read the texture from
4348 * Texture: Address to store the interface pointer at
4349 *
4350 * Returns:
4351 * D3D_OK on success
4352 * DDERR_INVALIDPARAMS if Texture is NULL
4353 * For details, see IWineD3DDevice::GetTexture
4354 *
4355 *****************************************************************************/
4356 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4357 DWORD stage, IDirectDrawSurface7 **texture)
4358 {
4359 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4360 struct wined3d_texture *wined3d_texture;
4361 struct ddraw_surface *surface;
4362 HRESULT hr;
4363
4364 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4365
4366 if (!texture)
4367 return DDERR_INVALIDPARAMS;
4368
4369 wined3d_mutex_lock();
4370 hr = wined3d_device_get_texture(device->wined3d_device, stage, &wined3d_texture);
4371 if (FAILED(hr) || !wined3d_texture)
4372 {
4373 *texture = NULL;
4374 wined3d_mutex_unlock();
4375 return hr;
4376 }
4377
4378 surface = wined3d_texture_get_parent(wined3d_texture);
4379 *texture = &surface->IDirectDrawSurface7_iface;
4380 IDirectDrawSurface7_AddRef(*texture);
4381 wined3d_texture_decref(wined3d_texture);
4382 wined3d_mutex_unlock();
4383
4384 return hr;
4385 }
4386
4387 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4388 DWORD stage, IDirectDrawSurface7 **Texture)
4389 {
4390 return d3d_device7_GetTexture(iface, stage, Texture);
4391 }
4392
4393 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4394 DWORD stage, IDirectDrawSurface7 **Texture)
4395 {
4396 HRESULT hr;
4397 WORD old_fpucw;
4398
4399 old_fpucw = d3d_fpu_setup();
4400 hr = d3d_device7_GetTexture(iface, stage, Texture);
4401 set_fpu_control_word(old_fpucw);
4402
4403 return hr;
4404 }
4405
4406 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4407 {
4408 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4409 struct ddraw_surface *ret_val_impl;
4410 HRESULT ret;
4411 IDirectDrawSurface7 *ret_val;
4412
4413 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4414
4415 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4416
4417 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4418 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4419
4420 TRACE("Returning texture %p.\n", *Texture2);
4421
4422 return ret;
4423 }
4424
4425 /*****************************************************************************
4426 * IDirect3DDevice7::SetTexture
4427 *
4428 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4429 *
4430 * Version 3 and 7
4431 *
4432 * Params:
4433 * Stage: The stage to assign the texture to
4434 * Texture: Interface pointer to the texture surface
4435 *
4436 * Returns
4437 * D3D_OK on success
4438 * For details, see IWineD3DDevice::SetTexture
4439 *
4440 *****************************************************************************/
4441 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4442 DWORD stage, IDirectDrawSurface7 *texture)
4443 {
4444 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4445 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4446 HRESULT hr;
4447
4448 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4449
4450 /* Texture may be NULL here */
4451 wined3d_mutex_lock();
4452 hr = wined3d_device_set_texture(device->wined3d_device,
4453 stage, surf ? surf->wined3d_texture : NULL);
4454 wined3d_mutex_unlock();
4455
4456 return hr;
4457 }
4458
4459 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4460 DWORD stage, IDirectDrawSurface7 *texture)
4461 {
4462 return d3d_device7_SetTexture(iface, stage, texture);
4463 }
4464
4465 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4466 DWORD stage, IDirectDrawSurface7 *texture)
4467 {
4468 HRESULT hr;
4469 WORD old_fpucw;
4470
4471 old_fpucw = d3d_fpu_setup();
4472 hr = d3d_device7_SetTexture(iface, stage, texture);
4473 set_fpu_control_word(old_fpucw);
4474
4475 return hr;
4476 }
4477
4478 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4479 DWORD stage, IDirect3DTexture2 *texture)
4480 {
4481 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4482 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4483 DWORD texmapblend;
4484 HRESULT hr;
4485
4486 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4487
4488 wined3d_mutex_lock();
4489
4490 if (device->legacyTextureBlending)
4491 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4492
4493 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4494
4495 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4496 {
4497 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4498 See d3d_device3_SetRenderState() for details. */
4499 struct wined3d_texture *tex = NULL;
4500 BOOL tex_alpha = FALSE;
4501 DDPIXELFORMAT ddfmt;
4502 HRESULT result;
4503
4504 result = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
4505 if (result == WINED3D_OK && tex)
4506 {
4507 struct wined3d_resource *sub_resource;
4508
4509 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4510 {
4511 struct wined3d_resource_desc desc;
4512
4513 wined3d_resource_get_desc(sub_resource, &desc);
4514 ddfmt.dwSize = sizeof(ddfmt);
4515 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4516 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4517 }
4518
4519 wined3d_texture_decref(tex);
4520 }
4521
4522 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4523 if (tex_alpha)
4524 wined3d_device_set_texture_stage_state(device->wined3d_device,
4525 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4526 else
4527 wined3d_device_set_texture_stage_state(device->wined3d_device,
4528 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4529 }
4530
4531 wined3d_mutex_unlock();
4532
4533 return hr;
4534 }
4535
4536 static const struct tss_lookup
4537 {
4538 BOOL sampler_state;
4539 enum wined3d_texture_stage_state state;
4540 }
4541 tss_lookup[] =
4542 {
4543 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4544 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4545 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4546 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4547 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4548 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4549 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4550 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4551 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4552 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4553 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4554 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4555 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4556 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4557 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4558 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4559 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4560 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4561 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4562 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4563 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4564 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4565 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4566 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4567 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4568 };
4569
4570 /*****************************************************************************
4571 * IDirect3DDevice7::GetTextureStageState
4572 *
4573 * Retrieves a state from a texture stage.
4574 *
4575 * Version 3 and 7
4576 *
4577 * Params:
4578 * Stage: The stage to retrieve the state from
4579 * TexStageStateType: The state type to retrieve
4580 * State: Address to store the state's value at
4581 *
4582 * Returns:
4583 * D3D_OK on success
4584 * DDERR_INVALIDPARAMS if State is NULL
4585 * For details, see IWineD3DDevice::GetTextureStageState
4586 *
4587 *****************************************************************************/
4588 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4589 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4590 {
4591 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4592 HRESULT hr;
4593 const struct tss_lookup *l;
4594
4595 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4596 iface, stage, state, value);
4597
4598 if (!value)
4599 return DDERR_INVALIDPARAMS;
4600
4601 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4602 {
4603 WARN("Invalid state %#x passed.\n", state);
4604 return DD_OK;
4605 }
4606
4607 l = &tss_lookup[state];
4608
4609 wined3d_mutex_lock();
4610
4611 if (l->sampler_state)
4612 {
4613 hr = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state, value);
4614
4615 switch (state)
4616 {
4617 /* Mipfilter is a sampler state with different values */
4618 case D3DTSS_MIPFILTER:
4619 {
4620 switch (*value)
4621 {
4622 case WINED3D_TEXF_NONE:
4623 *value = D3DTFP_NONE;
4624 break;
4625 case WINED3D_TEXF_POINT:
4626 *value = D3DTFP_POINT;
4627 break;
4628 case WINED3D_TEXF_LINEAR:
4629 *value = D3DTFP_LINEAR;
4630 break;
4631 default:
4632 ERR("Unexpected mipfilter value %#x.\n", *value);
4633 *value = D3DTFP_NONE;
4634 break;
4635 }
4636 break;
4637 }
4638
4639 /* Magfilter has slightly different values */
4640 case D3DTSS_MAGFILTER:
4641 {
4642 switch (*value)
4643 {
4644 case WINED3D_TEXF_POINT:
4645 *value = D3DTFG_POINT;
4646 break;
4647 case WINED3D_TEXF_LINEAR:
4648 *value = D3DTFG_LINEAR;
4649 break;
4650 case WINED3D_TEXF_ANISOTROPIC:
4651 *value = D3DTFG_ANISOTROPIC;
4652 break;
4653 case WINED3D_TEXF_FLAT_CUBIC:
4654 *value = D3DTFG_FLATCUBIC;
4655 break;
4656 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4657 *value = D3DTFG_GAUSSIANCUBIC;
4658 break;
4659 default:
4660 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4661 *value = D3DTFG_POINT;
4662 break;
4663 }
4664 break;
4665 }
4666
4667 default:
4668 break;
4669 }
4670 }
4671 else
4672 {
4673 hr = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state, value);
4674 }
4675
4676 wined3d_mutex_unlock();
4677
4678 return hr;
4679 }
4680
4681 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4682 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4683 {
4684 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4685 }
4686
4687 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4688 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4689 {
4690 HRESULT hr;
4691 WORD old_fpucw;
4692
4693 old_fpucw = d3d_fpu_setup();
4694 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4695 set_fpu_control_word(old_fpucw);
4696
4697 return hr;
4698 }
4699
4700 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4701 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4702 {
4703 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4704
4705 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4706 iface, stage, state, value);
4707
4708 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4709 }
4710
4711 /*****************************************************************************
4712 * IDirect3DDevice7::SetTextureStageState
4713 *
4714 * Sets a texture stage state. Some stage types need to be handled specially,
4715 * because they do not exist in WineD3D and were moved to another place
4716 *
4717 * Version 3 and 7
4718 *
4719 * Params:
4720 * Stage: The stage to modify
4721 * TexStageStateType: The state to change
4722 * State: The new value for the state
4723 *
4724 * Returns:
4725 * D3D_OK on success
4726 * For details, see IWineD3DDevice::SetTextureStageState
4727 *
4728 *****************************************************************************/
4729 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4730 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4731 {
4732 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4733 const struct tss_lookup *l;
4734 HRESULT hr;
4735
4736 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4737 iface, stage, state, value);
4738
4739 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4740 {
4741 WARN("Invalid state %#x passed.\n", state);
4742 return DD_OK;
4743 }
4744
4745 l = &tss_lookup[state];
4746
4747 wined3d_mutex_lock();
4748
4749 if (l->sampler_state)
4750 {
4751 switch (state)
4752 {
4753 /* Mipfilter is a sampler state with different values */
4754 case D3DTSS_MIPFILTER:
4755 {
4756 switch (value)
4757 {
4758 case D3DTFP_NONE:
4759 value = WINED3D_TEXF_NONE;
4760 break;
4761 case D3DTFP_POINT:
4762 value = WINED3D_TEXF_POINT;
4763 break;
4764 case 0: /* Unchecked */
4765 case D3DTFP_LINEAR:
4766 value = WINED3D_TEXF_LINEAR;
4767 break;
4768 default:
4769 ERR("Unexpected mipfilter value %#x.\n", value);
4770 value = WINED3D_TEXF_NONE;
4771 break;
4772 }
4773 break;
4774 }
4775
4776 /* Magfilter has slightly different values */
4777 case D3DTSS_MAGFILTER:
4778 {
4779 switch (value)
4780 {
4781 case D3DTFG_POINT:
4782 value = WINED3D_TEXF_POINT;
4783 break;
4784 case D3DTFG_LINEAR:
4785 value = WINED3D_TEXF_LINEAR;
4786 break;
4787 case D3DTFG_FLATCUBIC:
4788 value = WINED3D_TEXF_FLAT_CUBIC;
4789 break;
4790 case D3DTFG_GAUSSIANCUBIC:
4791 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
4792 break;
4793 case D3DTFG_ANISOTROPIC:
4794 value = WINED3D_TEXF_ANISOTROPIC;
4795 break;
4796 default:
4797 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
4798 value = WINED3D_TEXF_POINT;
4799 break;
4800 }
4801 break;
4802 }
4803
4804 case D3DTSS_ADDRESS:
4805 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
4806 break;
4807
4808 default:
4809 break;
4810 }
4811
4812 hr = wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
4813 }
4814 else
4815 {
4816 hr = wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
4817 }
4818
4819 wined3d_mutex_unlock();
4820
4821 return hr;
4822 }
4823
4824 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4825 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4826 {
4827 return d3d_device7_SetTextureStageState(iface, stage, state, value);
4828 }
4829
4830 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4831 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4832 {
4833 HRESULT hr;
4834 WORD old_fpucw;
4835
4836 old_fpucw = d3d_fpu_setup();
4837 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
4838 set_fpu_control_word(old_fpucw);
4839
4840 return hr;
4841 }
4842
4843 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
4844 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4845 {
4846 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4847
4848 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4849 iface, stage, state, value);
4850
4851 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4852 }
4853
4854 /*****************************************************************************
4855 * IDirect3DDevice7::ValidateDevice
4856 *
4857 * SDK: "Reports the device's ability to render the currently set
4858 * texture-blending operations in a single pass". Whatever that means
4859 * exactly...
4860 *
4861 * Version 3 and 7
4862 *
4863 * Params:
4864 * NumPasses: Address to write the number of necessary passes for the
4865 * desired effect to.
4866 *
4867 * Returns:
4868 * D3D_OK on success
4869 * See IWineD3DDevice::ValidateDevice for more details
4870 *
4871 *****************************************************************************/
4872 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
4873 {
4874 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4875 HRESULT hr;
4876
4877 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4878
4879 wined3d_mutex_lock();
4880 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
4881 wined3d_mutex_unlock();
4882
4883 return hr;
4884 }
4885
4886 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
4887 {
4888 return d3d_device7_ValidateDevice(iface, pass_count);
4889 }
4890
4891 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
4892 {
4893 HRESULT hr;
4894 WORD old_fpucw;
4895
4896 old_fpucw = d3d_fpu_setup();
4897 hr = d3d_device7_ValidateDevice(iface, pass_count);
4898 set_fpu_control_word(old_fpucw);
4899
4900 return hr;
4901 }
4902
4903 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
4904 {
4905 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4906
4907 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4908
4909 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
4910 }
4911
4912 /*****************************************************************************
4913 * IDirect3DDevice7::Clear
4914 *
4915 * Fills the render target, the z buffer and the stencil buffer with a
4916 * clear color / value
4917 *
4918 * Version 7 only
4919 *
4920 * Params:
4921 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4922 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4923 * Flags: Some flags, as usual
4924 * Color: Clear color for the render target
4925 * Z: Clear value for the Z buffer
4926 * Stencil: Clear value to store in each stencil buffer entry
4927 *
4928 * Returns:
4929 * D3D_OK on success
4930 * For details, see IWineD3DDevice::Clear
4931 *
4932 *****************************************************************************/
4933 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
4934 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4935 {
4936 const struct wined3d_color c =
4937 {
4938 ((color >> 16) & 0xff) / 255.0f,
4939 ((color >> 8) & 0xff) / 255.0f,
4940 (color & 0xff) / 255.0f,
4941 ((color >> 24) & 0xff) / 255.0f,
4942 };
4943 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4944 HRESULT hr;
4945
4946 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
4947 iface, count, rects, flags, color, z, stencil);
4948
4949 wined3d_mutex_lock();
4950 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
4951 wined3d_mutex_unlock();
4952
4953 return hr;
4954 }
4955
4956 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
4957 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4958 {
4959 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
4960 }
4961
4962 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
4963 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4964 {
4965 HRESULT hr;
4966 WORD old_fpucw;
4967
4968 old_fpucw = d3d_fpu_setup();
4969 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
4970 set_fpu_control_word(old_fpucw);
4971
4972 return hr;
4973 }
4974
4975 /*****************************************************************************
4976 * IDirect3DDevice7::SetViewport
4977 *
4978 * Sets the current viewport.
4979 *
4980 * Version 7 only, but IDirect3DViewport uses this call for older
4981 * versions
4982 *
4983 * Params:
4984 * Data: The new viewport to set
4985 *
4986 * Returns:
4987 * D3D_OK on success
4988 * DDERR_INVALIDPARAMS if Data is NULL
4989 * For more details, see IWineDDDevice::SetViewport
4990 *
4991 *****************************************************************************/
4992 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4993 {
4994 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4995 HRESULT hr;
4996
4997 TRACE("iface %p, viewport %p.\n", iface, viewport);
4998
4999 if (!viewport)
5000 return DDERR_INVALIDPARAMS;
5001
5002 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5003 wined3d_mutex_lock();
5004 hr = wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5005 wined3d_mutex_unlock();
5006
5007 return hr;
5008 }
5009
5010 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5011 {
5012 return d3d_device7_SetViewport(iface, viewport);
5013 }
5014
5015 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5016 {
5017 HRESULT hr;
5018 WORD old_fpucw;
5019
5020 old_fpucw = d3d_fpu_setup();
5021 hr = d3d_device7_SetViewport(iface, viewport);
5022 set_fpu_control_word(old_fpucw);
5023
5024 return hr;
5025 }
5026
5027 /*****************************************************************************
5028 * IDirect3DDevice::GetViewport
5029 *
5030 * Returns the current viewport
5031 *
5032 * Version 7
5033 *
5034 * Params:
5035 * Data: D3D7Viewport structure to write the viewport information to
5036 *
5037 * Returns:
5038 * D3D_OK on success
5039 * DDERR_INVALIDPARAMS if Data is NULL
5040 * For more details, see IWineD3DDevice::GetViewport
5041 *
5042 *****************************************************************************/
5043 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5044 {
5045 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5046 HRESULT hr;
5047
5048 TRACE("iface %p, viewport %p.\n", iface, viewport);
5049
5050 if (!viewport)
5051 return DDERR_INVALIDPARAMS;
5052
5053 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5054 wined3d_mutex_lock();
5055 hr = wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5056 wined3d_mutex_unlock();
5057
5058 return hr_ddraw_from_wined3d(hr);
5059 }
5060
5061 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5062 {
5063 return d3d_device7_GetViewport(iface, viewport);
5064 }
5065
5066 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5067 {
5068 HRESULT hr;
5069 WORD old_fpucw;
5070
5071 old_fpucw = d3d_fpu_setup();
5072 hr = d3d_device7_GetViewport(iface, viewport);
5073 set_fpu_control_word(old_fpucw);
5074
5075 return hr;
5076 }
5077
5078 /*****************************************************************************
5079 * IDirect3DDevice7::SetMaterial
5080 *
5081 * Sets the Material
5082 *
5083 * Version 7
5084 *
5085 * Params:
5086 * Mat: The material to set
5087 *
5088 * Returns:
5089 * D3D_OK on success
5090 * DDERR_INVALIDPARAMS if Mat is NULL.
5091 * For more details, see IWineD3DDevice::SetMaterial
5092 *
5093 *****************************************************************************/
5094 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5095 {
5096 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5097 HRESULT hr;
5098
5099 TRACE("iface %p, material %p.\n", iface, material);
5100
5101 if (!material)
5102 return DDERR_INVALIDPARAMS;
5103
5104 wined3d_mutex_lock();
5105 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5106 hr = wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5107 wined3d_mutex_unlock();
5108
5109 return hr_ddraw_from_wined3d(hr);
5110 }
5111
5112 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5113 {
5114 return d3d_device7_SetMaterial(iface, material);
5115 }
5116
5117 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5118 {
5119 HRESULT hr;
5120 WORD old_fpucw;
5121
5122 old_fpucw = d3d_fpu_setup();
5123 hr = d3d_device7_SetMaterial(iface, material);
5124 set_fpu_control_word(old_fpucw);
5125
5126 return hr;
5127 }
5128
5129 /*****************************************************************************
5130 * IDirect3DDevice7::GetMaterial
5131 *
5132 * Returns the current material
5133 *
5134 * Version 7
5135 *
5136 * Params:
5137 * Mat: D3DMATERIAL7 structure to write the material parameters to
5138 *
5139 * Returns:
5140 * D3D_OK on success
5141 * DDERR_INVALIDPARAMS if Mat is NULL
5142 * For more details, see IWineD3DDevice::GetMaterial
5143 *
5144 *****************************************************************************/
5145 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5146 {
5147 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5148 HRESULT hr;
5149
5150 TRACE("iface %p, material %p.\n", iface, material);
5151
5152 wined3d_mutex_lock();
5153 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5154 hr = wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5155 wined3d_mutex_unlock();
5156
5157 return hr_ddraw_from_wined3d(hr);
5158 }
5159
5160 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5161 {
5162 return d3d_device7_GetMaterial(iface, material);
5163 }
5164
5165 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5166 {
5167 HRESULT hr;
5168 WORD old_fpucw;
5169
5170 old_fpucw = d3d_fpu_setup();
5171 hr = d3d_device7_GetMaterial(iface, material);
5172 set_fpu_control_word(old_fpucw);
5173
5174 return hr;
5175 }
5176
5177 /*****************************************************************************
5178 * IDirect3DDevice7::SetLight
5179 *
5180 * Assigns a light to a light index, but doesn't activate it yet.
5181 *
5182 * Version 7, IDirect3DLight uses this method for older versions
5183 *
5184 * Params:
5185 * LightIndex: The index of the new light
5186 * Light: A D3DLIGHT7 structure describing the light
5187 *
5188 * Returns:
5189 * D3D_OK on success
5190 * For more details, see IWineD3DDevice::SetLight
5191 *
5192 *****************************************************************************/
5193 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5194 {
5195 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5196 HRESULT hr;
5197
5198 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5199
5200 wined3d_mutex_lock();
5201 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5202 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5203 wined3d_mutex_unlock();
5204
5205 return hr_ddraw_from_wined3d(hr);
5206 }
5207
5208 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5209 {
5210 return d3d_device7_SetLight(iface, light_idx, light);
5211 }
5212
5213 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5214 {
5215 HRESULT hr;
5216 WORD old_fpucw;
5217
5218 old_fpucw = d3d_fpu_setup();
5219 hr = d3d_device7_SetLight(iface, light_idx, light);
5220 set_fpu_control_word(old_fpucw);
5221
5222 return hr;
5223 }
5224
5225 /*****************************************************************************
5226 * IDirect3DDevice7::GetLight
5227 *
5228 * Returns the light assigned to a light index
5229 *
5230 * Params:
5231 * Light: Structure to write the light information to
5232 *
5233 * Returns:
5234 * D3D_OK on success
5235 * DDERR_INVALIDPARAMS if Light is NULL
5236 * For details, see IWineD3DDevice::GetLight
5237 *
5238 *****************************************************************************/
5239 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5240 {
5241 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5242 HRESULT rc;
5243
5244 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5245
5246 wined3d_mutex_lock();
5247 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5248 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5249 wined3d_mutex_unlock();
5250
5251 /* Translate the result. WineD3D returns other values than D3D7 */
5252 return hr_ddraw_from_wined3d(rc);
5253 }
5254
5255 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5256 {
5257 return d3d_device7_GetLight(iface, light_idx, light);
5258 }
5259
5260 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5261 {
5262 HRESULT hr;
5263 WORD old_fpucw;
5264
5265 old_fpucw = d3d_fpu_setup();
5266 hr = d3d_device7_GetLight(iface, light_idx, light);
5267 set_fpu_control_word(old_fpucw);
5268
5269 return hr;
5270 }
5271
5272 /*****************************************************************************
5273 * IDirect3DDevice7::BeginStateBlock
5274 *
5275 * Begins recording to a stateblock
5276 *
5277 * Version 7
5278 *
5279 * Returns:
5280 * D3D_OK on success
5281 * For details see IWineD3DDevice::BeginStateBlock
5282 *
5283 *****************************************************************************/
5284 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5285 {
5286 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5287 HRESULT hr;
5288
5289 TRACE("iface %p.\n", iface);
5290
5291 wined3d_mutex_lock();
5292 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5293 wined3d_mutex_unlock();
5294
5295 return hr_ddraw_from_wined3d(hr);
5296 }
5297
5298 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5299 {
5300 return d3d_device7_BeginStateBlock(iface);
5301 }
5302
5303 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5304 {
5305 HRESULT hr;
5306 WORD old_fpucw;
5307
5308 old_fpucw = d3d_fpu_setup();
5309 hr = d3d_device7_BeginStateBlock(iface);
5310 set_fpu_control_word(old_fpucw);
5311
5312 return hr;
5313 }
5314
5315 /*****************************************************************************
5316 * IDirect3DDevice7::EndStateBlock
5317 *
5318 * Stops recording to a state block and returns the created stateblock
5319 * handle.
5320 *
5321 * Version 7
5322 *
5323 * Params:
5324 * BlockHandle: Address to store the stateblock's handle to
5325 *
5326 * Returns:
5327 * D3D_OK on success
5328 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5329 * See IWineD3DDevice::EndStateBlock for more details
5330 *
5331 *****************************************************************************/
5332 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5333 {
5334 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5335 struct wined3d_stateblock *wined3d_sb;
5336 HRESULT hr;
5337 DWORD h;
5338
5339 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5340
5341 if (!stateblock)
5342 return DDERR_INVALIDPARAMS;
5343
5344 wined3d_mutex_lock();
5345
5346 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5347 if (FAILED(hr))
5348 {
5349 WARN("Failed to end stateblock, hr %#x.\n", hr);
5350 wined3d_mutex_unlock();
5351 *stateblock = 0;
5352 return hr_ddraw_from_wined3d(hr);
5353 }
5354
5355 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5356 if (h == DDRAW_INVALID_HANDLE)
5357 {
5358 ERR("Failed to allocate a stateblock handle.\n");
5359 wined3d_stateblock_decref(wined3d_sb);
5360 wined3d_mutex_unlock();
5361 *stateblock = 0;
5362 return DDERR_OUTOFMEMORY;
5363 }
5364
5365 wined3d_mutex_unlock();
5366 *stateblock = h + 1;
5367
5368 return hr_ddraw_from_wined3d(hr);
5369 }
5370
5371 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5372 {
5373 return d3d_device7_EndStateBlock(iface, stateblock);
5374 }
5375
5376 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5377 {
5378 HRESULT hr;
5379 WORD old_fpucw;
5380
5381 old_fpucw = d3d_fpu_setup();
5382 hr = d3d_device7_EndStateBlock(iface, stateblock);
5383 set_fpu_control_word(old_fpucw);
5384
5385 return hr;
5386 }
5387
5388 /*****************************************************************************
5389 * IDirect3DDevice7::PreLoad
5390 *
5391 * Allows the app to signal that a texture will be used soon, to allow
5392 * the Direct3DDevice to load it to the video card in the meantime.
5393 *
5394 * Version 7
5395 *
5396 * Params:
5397 * Texture: The texture to preload
5398 *
5399 * Returns:
5400 * D3D_OK on success
5401 * DDERR_INVALIDPARAMS if Texture is NULL
5402 * See IWineD3DSurface::PreLoad for details
5403 *
5404 *****************************************************************************/
5405 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5406 {
5407 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5408
5409 TRACE("iface %p, texture %p.\n", iface, texture);
5410
5411 if (!texture)
5412 return DDERR_INVALIDPARAMS;
5413
5414 wined3d_mutex_lock();
5415 wined3d_surface_preload(surface->wined3d_surface);
5416 wined3d_mutex_unlock();
5417
5418 return D3D_OK;
5419 }
5420
5421 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5422 {
5423 return d3d_device7_PreLoad(iface, texture);
5424 }
5425
5426 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5427 {
5428 HRESULT hr;
5429 WORD old_fpucw;
5430
5431 old_fpucw = d3d_fpu_setup();
5432 hr = d3d_device7_PreLoad(iface, texture);
5433 set_fpu_control_word(old_fpucw);
5434
5435 return hr;
5436 }
5437
5438 /*****************************************************************************
5439 * IDirect3DDevice7::ApplyStateBlock
5440 *
5441 * Activates the state stored in a state block handle.
5442 *
5443 * Params:
5444 * BlockHandle: The stateblock handle to activate
5445 *
5446 * Returns:
5447 * D3D_OK on success
5448 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5449 *
5450 *****************************************************************************/
5451 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5452 {
5453 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5454 struct wined3d_stateblock *wined3d_sb;
5455 HRESULT hr;
5456
5457 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5458
5459 wined3d_mutex_lock();
5460 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5461 if (!wined3d_sb)
5462 {
5463 WARN("Invalid stateblock handle.\n");
5464 wined3d_mutex_unlock();
5465 return D3DERR_INVALIDSTATEBLOCK;
5466 }
5467
5468 hr = wined3d_stateblock_apply(wined3d_sb);
5469 wined3d_mutex_unlock();
5470
5471 return hr_ddraw_from_wined3d(hr);
5472 }
5473
5474 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5475 {
5476 return d3d_device7_ApplyStateBlock(iface, stateblock);
5477 }
5478
5479 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5480 {
5481 HRESULT hr;
5482 WORD old_fpucw;
5483
5484 old_fpucw = d3d_fpu_setup();
5485 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5486 set_fpu_control_word(old_fpucw);
5487
5488 return hr;
5489 }
5490
5491 /*****************************************************************************
5492 * IDirect3DDevice7::CaptureStateBlock
5493 *
5494 * Updates a stateblock's values to the values currently set for the device
5495 *
5496 * Version 7
5497 *
5498 * Params:
5499 * BlockHandle: Stateblock to update
5500 *
5501 * Returns:
5502 * D3D_OK on success
5503 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5504 * See IWineD3DDevice::CaptureStateBlock for more details
5505 *
5506 *****************************************************************************/
5507 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5508 {
5509 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5510 struct wined3d_stateblock *wined3d_sb;
5511 HRESULT hr;
5512
5513 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5514
5515 wined3d_mutex_lock();
5516 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5517 if (!wined3d_sb)
5518 {
5519 WARN("Invalid stateblock handle.\n");
5520 wined3d_mutex_unlock();
5521 return D3DERR_INVALIDSTATEBLOCK;
5522 }
5523
5524 hr = wined3d_stateblock_capture(wined3d_sb);
5525 wined3d_mutex_unlock();
5526
5527 return hr_ddraw_from_wined3d(hr);
5528 }
5529
5530 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5531 {
5532 return d3d_device7_CaptureStateBlock(iface, stateblock);
5533 }
5534
5535 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5536 {
5537 HRESULT hr;
5538 WORD old_fpucw;
5539
5540 old_fpucw = d3d_fpu_setup();
5541 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5542 set_fpu_control_word(old_fpucw);
5543
5544 return hr;
5545 }
5546
5547 /*****************************************************************************
5548 * IDirect3DDevice7::DeleteStateBlock
5549 *
5550 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5551 *
5552 * Version 7
5553 *
5554 * Params:
5555 * BlockHandle: Stateblock handle to delete
5556 *
5557 * Returns:
5558 * D3D_OK on success
5559 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5560 *
5561 *****************************************************************************/
5562 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5563 {
5564 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5565 struct wined3d_stateblock *wined3d_sb;
5566 ULONG ref;
5567
5568 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5569
5570 wined3d_mutex_lock();
5571
5572 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5573 if (!wined3d_sb)
5574 {
5575 WARN("Invalid stateblock handle.\n");
5576 wined3d_mutex_unlock();
5577 return D3DERR_INVALIDSTATEBLOCK;
5578 }
5579
5580 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5581 {
5582 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5583 }
5584
5585 wined3d_mutex_unlock();
5586
5587 return D3D_OK;
5588 }
5589
5590 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5591 {
5592 return d3d_device7_DeleteStateBlock(iface, stateblock);
5593 }
5594
5595 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5596 {
5597 HRESULT hr;
5598 WORD old_fpucw;
5599
5600 old_fpucw = d3d_fpu_setup();
5601 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5602 set_fpu_control_word(old_fpucw);
5603
5604 return hr;
5605 }
5606
5607 /*****************************************************************************
5608 * IDirect3DDevice7::CreateStateBlock
5609 *
5610 * Creates a new state block handle.
5611 *
5612 * Version 7
5613 *
5614 * Params:
5615 * Type: The state block type
5616 * BlockHandle: Address to write the created handle to
5617 *
5618 * Returns:
5619 * D3D_OK on success
5620 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5621 *
5622 *****************************************************************************/
5623 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5624 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5625 {
5626 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5627 struct wined3d_stateblock *wined3d_sb;
5628 HRESULT hr;
5629 DWORD h;
5630
5631 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5632
5633 if (!stateblock)
5634 return DDERR_INVALIDPARAMS;
5635
5636 if (type != D3DSBT_ALL
5637 && type != D3DSBT_PIXELSTATE
5638 && type != D3DSBT_VERTEXSTATE)
5639 {
5640 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5641 return DDERR_INVALIDPARAMS;
5642 }
5643
5644 wined3d_mutex_lock();
5645
5646 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5647 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5648 if (FAILED(hr))
5649 {
5650 WARN("Failed to create stateblock, hr %#x.\n", hr);
5651 wined3d_mutex_unlock();
5652 return hr_ddraw_from_wined3d(hr);
5653 }
5654
5655 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5656 if (h == DDRAW_INVALID_HANDLE)
5657 {
5658 ERR("Failed to allocate stateblock handle.\n");
5659 wined3d_stateblock_decref(wined3d_sb);
5660 wined3d_mutex_unlock();
5661 return DDERR_OUTOFMEMORY;
5662 }
5663
5664 *stateblock = h + 1;
5665 wined3d_mutex_unlock();
5666
5667 return hr_ddraw_from_wined3d(hr);
5668 }
5669
5670 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5671 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5672 {
5673 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5674 }
5675
5676 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5677 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5678 {
5679 HRESULT hr;
5680 WORD old_fpucw;
5681
5682 old_fpucw = d3d_fpu_setup();
5683 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5684 set_fpu_control_word(old_fpucw);
5685
5686 return hr;
5687 }
5688
5689 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5690 {
5691 struct ddraw_surface *src_level, *dest_level;
5692 IDirectDrawSurface7 *temp;
5693 DDSURFACEDESC2 ddsd;
5694 BOOL levelFound; /* at least one suitable sublevel in dest found */
5695
5696 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5697 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5698 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5699 */
5700 levelFound = FALSE;
5701
5702 src_level = src;
5703 dest_level = dest;
5704
5705 for (;src_level && dest_level;)
5706 {
5707 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5708 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5709 {
5710 levelFound = TRUE;
5711
5712 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5713 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5714 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5715
5716 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5717
5718 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5719 }
5720
5721 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5722 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5723 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5724
5725 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5726
5727 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5728 }
5729
5730 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5731 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5732
5733 return !dest_level && levelFound;
5734 }
5735
5736 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dest,
5737 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5738 {
5739 struct ddraw_surface *src_level, *dest_level;
5740 IDirectDrawSurface7 *temp;
5741 DDSURFACEDESC2 ddsd;
5742 POINT point;
5743 RECT src_rect;
5744 HRESULT hr;
5745 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5746 DWORD ckeyflag;
5747 DDCOLORKEY ddckey;
5748
5749 /* Copy palette, if possible. */
5750 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5751 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5752
5753 if (pal_src != NULL && pal != NULL)
5754 {
5755 PALETTEENTRY palent[256];
5756
5757 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5758 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5759 }
5760
5761 if (pal) IDirectDrawPalette_Release(pal);
5762 if (pal_src) IDirectDrawPalette_Release(pal_src);
5763
5764 /* Copy colorkeys, if present. */
5765 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5766 {
5767 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5768
5769 if (SUCCEEDED(hr))
5770 {
5771 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5772 }
5773 }
5774
5775 src_level = src;
5776 dest_level = dest;
5777
5778 point = *DestPoint;
5779 src_rect = *SrcRect;
5780
5781 for (;src_level && dest_level;)
5782 {
5783 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5784 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5785 {
5786 UINT src_w = src_rect.right - src_rect.left;
5787 UINT src_h = src_rect.bottom - src_rect.top;
5788 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
5789
5790 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
5791 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
5792 ERR("Blit failed, hr %#x.\n", hr);
5793
5794 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5795 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5796 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5797
5798 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5799
5800 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5801 }
5802
5803 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5804 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5805 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5806
5807 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5808
5809 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5810
5811 point.x /= 2;
5812 point.y /= 2;
5813
5814 src_rect.top /= 2;
5815 src_rect.left /= 2;
5816 src_rect.right = (src_rect.right + 1) / 2;
5817 src_rect.bottom = (src_rect.bottom + 1) / 2;
5818 }
5819
5820 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5821 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5822 }
5823
5824 /*****************************************************************************
5825 * IDirect3DDevice7::Load
5826 *
5827 * Loads a rectangular area from the source into the destination texture.
5828 * It can also copy the source to the faces of a cubic environment map
5829 *
5830 * Version 7
5831 *
5832 * Params:
5833 * DestTex: Destination texture
5834 * DestPoint: Point in the destination where the source image should be
5835 * written to
5836 * SrcTex: Source texture
5837 * SrcRect: Source rectangle
5838 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
5839 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
5840 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
5841 *
5842 * Returns:
5843 * D3D_OK on success
5844 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
5845 *
5846 *
5847 *****************************************************************************/
5848 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
5849 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5850 {
5851 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5852 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
5853 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
5854 POINT destpoint;
5855 RECT srcrect;
5856
5857 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
5858 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
5859
5860 if( (!src) || (!dest) )
5861 return DDERR_INVALIDPARAMS;
5862
5863 wined3d_mutex_lock();
5864
5865 if (!src_rect)
5866 {
5867 srcrect.left = srcrect.top = 0;
5868 srcrect.right = src->surface_desc.dwWidth;
5869 srcrect.bottom = src->surface_desc.dwHeight;
5870 }
5871 else
5872 srcrect = *src_rect;
5873
5874 if (!dst_pos)
5875 destpoint.x = destpoint.y = 0;
5876 else
5877 destpoint = *dst_pos;
5878
5879 /* Check bad dimensions. dst_pos is validated against src, not dest, because
5880 * destination can be a subset of mip levels, in which case actual coordinates used
5881 * for it may be divided. If any dimension of dest is larger than source, it can't be
5882 * mip level subset, so an error can be returned early.
5883 */
5884 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
5885 srcrect.right > src->surface_desc.dwWidth ||
5886 srcrect.bottom > src->surface_desc.dwHeight ||
5887 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
5888 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
5889 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
5890 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
5891 {
5892 wined3d_mutex_unlock();
5893 return DDERR_INVALIDPARAMS;
5894 }
5895
5896 /* Must be top level surfaces. */
5897 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
5898 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
5899 {
5900 wined3d_mutex_unlock();
5901 return DDERR_INVALIDPARAMS;
5902 }
5903
5904 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5905 {
5906 struct ddraw_surface *src_face, *dest_face;
5907 DWORD src_face_flag, dest_face_flag;
5908 IDirectDrawSurface7 *temp;
5909 DDSURFACEDESC2 ddsd;
5910 int i;
5911
5912 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5913 {
5914 wined3d_mutex_unlock();
5915 return DDERR_INVALIDPARAMS;
5916 }
5917
5918 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
5919 * time it's actual surface loading. */
5920 for (i = 0; i < 2; i++)
5921 {
5922 dest_face = dest;
5923 src_face = src;
5924
5925 for (;dest_face && src_face;)
5926 {
5927 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5928 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5929
5930 if (src_face_flag == dest_face_flag)
5931 {
5932 if (i == 0)
5933 {
5934 /* Destination mip levels must be subset of source mip levels. */
5935 if (!is_mip_level_subset(dest_face, src_face))
5936 {
5937 wined3d_mutex_unlock();
5938 return DDERR_INVALIDPARAMS;
5939 }
5940 }
5941 else if (flags & dest_face_flag)
5942 {
5943 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
5944 }
5945
5946 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
5947 {
5948 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5949 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
5950 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5951
5952 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
5953
5954 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
5955 }
5956 else
5957 {
5958 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
5959
5960 src_face = NULL;
5961 }
5962 }
5963
5964 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
5965 {
5966 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5967 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
5968 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5969
5970 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
5971
5972 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
5973 }
5974 else
5975 {
5976 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
5977
5978 dest_face = NULL;
5979 }
5980 }
5981
5982 if (i == 0)
5983 {
5984 /* Native returns error if src faces are not subset of dest faces. */
5985 if (src_face)
5986 {
5987 wined3d_mutex_unlock();
5988 return DDERR_INVALIDPARAMS;
5989 }
5990 }
5991 }
5992
5993 wined3d_mutex_unlock();
5994 return D3D_OK;
5995 }
5996 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5997 {
5998 wined3d_mutex_unlock();
5999 return DDERR_INVALIDPARAMS;
6000 }
6001
6002 /* Handle non cube map textures. */
6003
6004 /* Destination mip levels must be subset of source mip levels. */
6005 if (!is_mip_level_subset(dest, src))
6006 {
6007 wined3d_mutex_unlock();
6008 return DDERR_INVALIDPARAMS;
6009 }
6010
6011 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6012
6013 wined3d_mutex_unlock();
6014
6015 return D3D_OK;
6016 }
6017
6018 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6019 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6020 {
6021 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6022 }
6023
6024 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6025 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6026 {
6027 HRESULT hr;
6028 WORD old_fpucw;
6029
6030 old_fpucw = d3d_fpu_setup();
6031 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6032 set_fpu_control_word(old_fpucw);
6033
6034 return hr;
6035 }
6036
6037 /*****************************************************************************
6038 * IDirect3DDevice7::LightEnable
6039 *
6040 * Enables or disables a light
6041 *
6042 * Version 7, IDirect3DLight uses this method too.
6043 *
6044 * Params:
6045 * LightIndex: The index of the light to enable / disable
6046 * Enable: Enable or disable the light
6047 *
6048 * Returns:
6049 * D3D_OK on success
6050 * For more details, see IWineD3DDevice::SetLightEnable
6051 *
6052 *****************************************************************************/
6053 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6054 {
6055 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6056 HRESULT hr;
6057
6058 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6059
6060 wined3d_mutex_lock();
6061 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6062 wined3d_mutex_unlock();
6063
6064 return hr_ddraw_from_wined3d(hr);
6065 }
6066
6067 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6068 {
6069 return d3d_device7_LightEnable(iface, light_idx, enabled);
6070 }
6071
6072 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6073 {
6074 HRESULT hr;
6075 WORD old_fpucw;
6076
6077 old_fpucw = d3d_fpu_setup();
6078 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6079 set_fpu_control_word(old_fpucw);
6080
6081 return hr;
6082 }
6083
6084 /*****************************************************************************
6085 * IDirect3DDevice7::GetLightEnable
6086 *
6087 * Retrieves if the light with the given index is enabled or not
6088 *
6089 * Version 7
6090 *
6091 * Params:
6092 * LightIndex: Index of desired light
6093 * Enable: Pointer to a BOOL which contains the result
6094 *
6095 * Returns:
6096 * D3D_OK on success
6097 * DDERR_INVALIDPARAMS if Enable is NULL
6098 * See IWineD3DDevice::GetLightEnable for more details
6099 *
6100 *****************************************************************************/
6101 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6102 {
6103 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6104 HRESULT hr;
6105
6106 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6107
6108 if (!enabled)
6109 return DDERR_INVALIDPARAMS;
6110
6111 wined3d_mutex_lock();
6112 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6113 wined3d_mutex_unlock();
6114
6115 return hr_ddraw_from_wined3d(hr);
6116 }
6117
6118 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6119 {
6120 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6121 }
6122
6123 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6124 {
6125 HRESULT hr;
6126 WORD old_fpucw;
6127
6128 old_fpucw = d3d_fpu_setup();
6129 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6130 set_fpu_control_word(old_fpucw);
6131
6132 return hr;
6133 }
6134
6135 /*****************************************************************************
6136 * IDirect3DDevice7::SetClipPlane
6137 *
6138 * Sets custom clipping plane
6139 *
6140 * Version 7
6141 *
6142 * Params:
6143 * Index: The index of the clipping plane
6144 * PlaneEquation: An equation defining the clipping plane
6145 *
6146 * Returns:
6147 * D3D_OK on success
6148 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6149 * See IWineD3DDevice::SetClipPlane for more details
6150 *
6151 *****************************************************************************/
6152 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6153 {
6154 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6155 HRESULT hr;
6156
6157 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6158
6159 if (!plane)
6160 return DDERR_INVALIDPARAMS;
6161
6162 wined3d_mutex_lock();
6163 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6164 wined3d_mutex_unlock();
6165
6166 return hr;
6167 }
6168
6169 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6170 {
6171 return d3d_device7_SetClipPlane(iface, idx, plane);
6172 }
6173
6174 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6175 {
6176 HRESULT hr;
6177 WORD old_fpucw;
6178
6179 old_fpucw = d3d_fpu_setup();
6180 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6181 set_fpu_control_word(old_fpucw);
6182
6183 return hr;
6184 }
6185
6186 /*****************************************************************************
6187 * IDirect3DDevice7::GetClipPlane
6188 *
6189 * Returns the clipping plane with a specific index
6190 *
6191 * Params:
6192 * Index: The index of the desired plane
6193 * PlaneEquation: Address to store the plane equation to
6194 *
6195 * Returns:
6196 * D3D_OK on success
6197 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6198 * See IWineD3DDevice::GetClipPlane for more details
6199 *
6200 *****************************************************************************/
6201 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6202 {
6203 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6204 HRESULT hr;
6205
6206 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6207
6208 if (!plane)
6209 return DDERR_INVALIDPARAMS;
6210
6211 wined3d_mutex_lock();
6212 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6213 wined3d_mutex_unlock();
6214
6215 return hr;
6216 }
6217
6218 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6219 {
6220 return d3d_device7_GetClipPlane(iface, idx, plane);
6221 }
6222
6223 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6224 {
6225 HRESULT hr;
6226 WORD old_fpucw;
6227
6228 old_fpucw = d3d_fpu_setup();
6229 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6230 set_fpu_control_word(old_fpucw);
6231
6232 return hr;
6233 }
6234
6235 /*****************************************************************************
6236 * IDirect3DDevice7::GetInfo
6237 *
6238 * Retrieves some information about the device. The DirectX sdk says that
6239 * this version returns S_FALSE for all retail builds of DirectX, that's what
6240 * this implementation does.
6241 *
6242 * Params:
6243 * DevInfoID: Information type requested
6244 * DevInfoStruct: Pointer to a structure to store the info to
6245 * Size: Size of the structure
6246 *
6247 * Returns:
6248 * S_FALSE, because it's a non-debug driver
6249 *
6250 *****************************************************************************/
6251 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6252 {
6253 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6254 iface, info_id, info, info_size);
6255
6256 if (TRACE_ON(ddraw))
6257 {
6258 TRACE(" info requested : ");
6259 switch (info_id)
6260 {
6261 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6262 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6263 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6264 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6265 }
6266 }
6267
6268 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6269 }
6270
6271 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6272 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6273 * are not duplicated.
6274
6275 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6276 * has already been setup for optimal d3d operation.
6277
6278 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6279 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6280 * by Sacrifice (game). */
6281 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6282 {
6283 /*** IUnknown Methods ***/
6284 d3d_device7_QueryInterface,
6285 d3d_device7_AddRef,
6286 d3d_device7_Release,
6287 /*** IDirect3DDevice7 ***/
6288 d3d_device7_GetCaps_FPUSetup,
6289 d3d_device7_EnumTextureFormats_FPUSetup,
6290 d3d_device7_BeginScene_FPUSetup,
6291 d3d_device7_EndScene_FPUSetup,
6292 d3d_device7_GetDirect3D,
6293 d3d_device7_SetRenderTarget_FPUSetup,
6294 d3d_device7_GetRenderTarget,
6295 d3d_device7_Clear_FPUSetup,
6296 d3d_device7_SetTransform_FPUSetup,
6297 d3d_device7_GetTransform_FPUSetup,
6298 d3d_device7_SetViewport_FPUSetup,
6299 d3d_device7_MultiplyTransform_FPUSetup,
6300 d3d_device7_GetViewport_FPUSetup,
6301 d3d_device7_SetMaterial_FPUSetup,
6302 d3d_device7_GetMaterial_FPUSetup,
6303 d3d_device7_SetLight_FPUSetup,
6304 d3d_device7_GetLight_FPUSetup,
6305 d3d_device7_SetRenderState_FPUSetup,
6306 d3d_device7_GetRenderState_FPUSetup,
6307 d3d_device7_BeginStateBlock_FPUSetup,
6308 d3d_device7_EndStateBlock_FPUSetup,
6309 d3d_device7_PreLoad_FPUSetup,
6310 d3d_device7_DrawPrimitive_FPUSetup,
6311 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6312 d3d_device7_SetClipStatus,
6313 d3d_device7_GetClipStatus,
6314 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6315 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6316 d3d_device7_DrawPrimitiveVB_FPUSetup,
6317 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6318 d3d_device7_ComputeSphereVisibility,
6319 d3d_device7_GetTexture_FPUSetup,
6320 d3d_device7_SetTexture_FPUSetup,
6321 d3d_device7_GetTextureStageState_FPUSetup,
6322 d3d_device7_SetTextureStageState_FPUSetup,
6323 d3d_device7_ValidateDevice_FPUSetup,
6324 d3d_device7_ApplyStateBlock_FPUSetup,
6325 d3d_device7_CaptureStateBlock_FPUSetup,
6326 d3d_device7_DeleteStateBlock_FPUSetup,
6327 d3d_device7_CreateStateBlock_FPUSetup,
6328 d3d_device7_Load_FPUSetup,
6329 d3d_device7_LightEnable_FPUSetup,
6330 d3d_device7_GetLightEnable_FPUSetup,
6331 d3d_device7_SetClipPlane_FPUSetup,
6332 d3d_device7_GetClipPlane_FPUSetup,
6333 d3d_device7_GetInfo
6334 };
6335
6336 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6337 {
6338 /*** IUnknown Methods ***/
6339 d3d_device7_QueryInterface,
6340 d3d_device7_AddRef,
6341 d3d_device7_Release,
6342 /*** IDirect3DDevice7 ***/
6343 d3d_device7_GetCaps_FPUPreserve,
6344 d3d_device7_EnumTextureFormats_FPUPreserve,
6345 d3d_device7_BeginScene_FPUPreserve,
6346 d3d_device7_EndScene_FPUPreserve,
6347 d3d_device7_GetDirect3D,
6348 d3d_device7_SetRenderTarget_FPUPreserve,
6349 d3d_device7_GetRenderTarget,
6350 d3d_device7_Clear_FPUPreserve,
6351 d3d_device7_SetTransform_FPUPreserve,
6352 d3d_device7_GetTransform_FPUPreserve,
6353 d3d_device7_SetViewport_FPUPreserve,
6354 d3d_device7_MultiplyTransform_FPUPreserve,
6355 d3d_device7_GetViewport_FPUPreserve,
6356 d3d_device7_SetMaterial_FPUPreserve,
6357 d3d_device7_GetMaterial_FPUPreserve,
6358 d3d_device7_SetLight_FPUPreserve,
6359 d3d_device7_GetLight_FPUPreserve,
6360 d3d_device7_SetRenderState_FPUPreserve,
6361 d3d_device7_GetRenderState_FPUPreserve,
6362 d3d_device7_BeginStateBlock_FPUPreserve,
6363 d3d_device7_EndStateBlock_FPUPreserve,
6364 d3d_device7_PreLoad_FPUPreserve,
6365 d3d_device7_DrawPrimitive_FPUPreserve,
6366 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6367 d3d_device7_SetClipStatus,
6368 d3d_device7_GetClipStatus,
6369 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6370 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6371 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6372 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6373 d3d_device7_ComputeSphereVisibility,
6374 d3d_device7_GetTexture_FPUPreserve,
6375 d3d_device7_SetTexture_FPUPreserve,
6376 d3d_device7_GetTextureStageState_FPUPreserve,
6377 d3d_device7_SetTextureStageState_FPUPreserve,
6378 d3d_device7_ValidateDevice_FPUPreserve,
6379 d3d_device7_ApplyStateBlock_FPUPreserve,
6380 d3d_device7_CaptureStateBlock_FPUPreserve,
6381 d3d_device7_DeleteStateBlock_FPUPreserve,
6382 d3d_device7_CreateStateBlock_FPUPreserve,
6383 d3d_device7_Load_FPUPreserve,
6384 d3d_device7_LightEnable_FPUPreserve,
6385 d3d_device7_GetLightEnable_FPUPreserve,
6386 d3d_device7_SetClipPlane_FPUPreserve,
6387 d3d_device7_GetClipPlane_FPUPreserve,
6388 d3d_device7_GetInfo
6389 };
6390
6391 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6392 {
6393 /*** IUnknown Methods ***/
6394 d3d_device3_QueryInterface,
6395 d3d_device3_AddRef,
6396 d3d_device3_Release,
6397 /*** IDirect3DDevice3 ***/
6398 d3d_device3_GetCaps,
6399 d3d_device3_GetStats,
6400 d3d_device3_AddViewport,
6401 d3d_device3_DeleteViewport,
6402 d3d_device3_NextViewport,
6403 d3d_device3_EnumTextureFormats,
6404 d3d_device3_BeginScene,
6405 d3d_device3_EndScene,
6406 d3d_device3_GetDirect3D,
6407 d3d_device3_SetCurrentViewport,
6408 d3d_device3_GetCurrentViewport,
6409 d3d_device3_SetRenderTarget,
6410 d3d_device3_GetRenderTarget,
6411 d3d_device3_Begin,
6412 d3d_device3_BeginIndexed,
6413 d3d_device3_Vertex,
6414 d3d_device3_Index,
6415 d3d_device3_End,
6416 d3d_device3_GetRenderState,
6417 d3d_device3_SetRenderState,
6418 d3d_device3_GetLightState,
6419 d3d_device3_SetLightState,
6420 d3d_device3_SetTransform,
6421 d3d_device3_GetTransform,
6422 d3d_device3_MultiplyTransform,
6423 d3d_device3_DrawPrimitive,
6424 d3d_device3_DrawIndexedPrimitive,
6425 d3d_device3_SetClipStatus,
6426 d3d_device3_GetClipStatus,
6427 d3d_device3_DrawPrimitiveStrided,
6428 d3d_device3_DrawIndexedPrimitiveStrided,
6429 d3d_device3_DrawPrimitiveVB,
6430 d3d_device3_DrawIndexedPrimitiveVB,
6431 d3d_device3_ComputeSphereVisibility,
6432 d3d_device3_GetTexture,
6433 d3d_device3_SetTexture,
6434 d3d_device3_GetTextureStageState,
6435 d3d_device3_SetTextureStageState,
6436 d3d_device3_ValidateDevice
6437 };
6438
6439 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6440 {
6441 /*** IUnknown Methods ***/
6442 d3d_device2_QueryInterface,
6443 d3d_device2_AddRef,
6444 d3d_device2_Release,
6445 /*** IDirect3DDevice2 ***/
6446 d3d_device2_GetCaps,
6447 d3d_device2_SwapTextureHandles,
6448 d3d_device2_GetStats,
6449 d3d_device2_AddViewport,
6450 d3d_device2_DeleteViewport,
6451 d3d_device2_NextViewport,
6452 d3d_device2_EnumTextureFormats,
6453 d3d_device2_BeginScene,
6454 d3d_device2_EndScene,
6455 d3d_device2_GetDirect3D,
6456 d3d_device2_SetCurrentViewport,
6457 d3d_device2_GetCurrentViewport,
6458 d3d_device2_SetRenderTarget,
6459 d3d_device2_GetRenderTarget,
6460 d3d_device2_Begin,
6461 d3d_device2_BeginIndexed,
6462 d3d_device2_Vertex,
6463 d3d_device2_Index,
6464 d3d_device2_End,
6465 d3d_device2_GetRenderState,
6466 d3d_device2_SetRenderState,
6467 d3d_device2_GetLightState,
6468 d3d_device2_SetLightState,
6469 d3d_device2_SetTransform,
6470 d3d_device2_GetTransform,
6471 d3d_device2_MultiplyTransform,
6472 d3d_device2_DrawPrimitive,
6473 d3d_device2_DrawIndexedPrimitive,
6474 d3d_device2_SetClipStatus,
6475 d3d_device2_GetClipStatus
6476 };
6477
6478 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6479 {
6480 /*** IUnknown Methods ***/
6481 d3d_device1_QueryInterface,
6482 d3d_device1_AddRef,
6483 d3d_device1_Release,
6484 /*** IDirect3DDevice1 ***/
6485 d3d_device1_Initialize,
6486 d3d_device1_GetCaps,
6487 d3d_device1_SwapTextureHandles,
6488 d3d_device1_CreateExecuteBuffer,
6489 d3d_device1_GetStats,
6490 d3d_device1_Execute,
6491 d3d_device1_AddViewport,
6492 d3d_device1_DeleteViewport,
6493 d3d_device1_NextViewport,
6494 d3d_device1_Pick,
6495 d3d_device1_GetPickRecords,
6496 d3d_device1_EnumTextureFormats,
6497 d3d_device1_CreateMatrix,
6498 d3d_device1_SetMatrix,
6499 d3d_device1_GetMatrix,
6500 d3d_device1_DeleteMatrix,
6501 d3d_device1_BeginScene,
6502 d3d_device1_EndScene,
6503 d3d_device1_GetDirect3D
6504 };
6505
6506 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6507 {
6508 d3d_device_inner_QueryInterface,
6509 d3d_device_inner_AddRef,
6510 d3d_device_inner_Release,
6511 };
6512
6513 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6514 {
6515 if (!iface) return NULL;
6516 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6517 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6518 }
6519
6520 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6521 {
6522 if (!iface) return NULL;
6523 assert(iface->lpVtbl == &d3d_device3_vtbl);
6524 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6525 }
6526
6527 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6528 {
6529 if (!iface) return NULL;
6530 assert(iface->lpVtbl == &d3d_device2_vtbl);
6531 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6532 }
6533
6534 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6535 {
6536 if (!iface) return NULL;
6537 assert(iface->lpVtbl == &d3d_device1_vtbl);
6538 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6539 }
6540
6541 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6542 {
6543 IDirectDrawSurface7 *depthStencil = NULL;
6544 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
6545 struct ddraw_surface *dsi;
6546
6547 IDirectDrawSurface7_GetAttachedSurface(&device->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6548 if (!depthStencil)
6549 {
6550 TRACE("Setting wined3d depth stencil to NULL\n");
6551 wined3d_device_set_depth_stencil(device->wined3d_device, NULL);
6552 return WINED3D_ZB_FALSE;
6553 }
6554
6555 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6556 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6557 wined3d_device_set_depth_stencil(device->wined3d_device, dsi->wined3d_surface);
6558
6559 IDirectDrawSurface7_Release(depthStencil);
6560 return WINED3D_ZB_TRUE;
6561 }
6562
6563 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6564 struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
6565 {
6566 static const D3DMATRIX ident =
6567 {
6568 1.0f, 0.0f, 0.0f, 0.0f,
6569 0.0f, 1.0f, 0.0f, 0.0f,
6570 0.0f, 0.0f, 1.0f, 0.0f,
6571 0.0f, 0.0f, 0.0f, 1.0f,
6572 };
6573 HRESULT hr;
6574
6575 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6576 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6577 else
6578 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6579
6580 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6581 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6582 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6583 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6584 device->ref = 1;
6585 device->version = version;
6586
6587 if (outer_unknown)
6588 device->outer_unknown = outer_unknown;
6589 else
6590 device->outer_unknown = &device->IUnknown_inner;
6591
6592 device->ddraw = ddraw;
6593 device->target = target;
6594 list_init(&device->viewport_list);
6595
6596 if (!ddraw_handle_table_init(&device->handle_table, 64))
6597 {
6598 ERR("Failed to initialize handle table.\n");
6599 return DDERR_OUTOFMEMORY;
6600 }
6601
6602 device->legacyTextureBlending = FALSE;
6603 device->legacy_projection = ident;
6604 device->legacy_clipspace = ident;
6605
6606 /* Create an index buffer, it's needed for indexed drawing */
6607 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6608 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3D_POOL_DEFAULT, NULL,
6609 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6610 if (FAILED(hr))
6611 {
6612 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6613 ddraw_handle_table_destroy(&device->handle_table);
6614 return hr;
6615 }
6616
6617 /* This is for convenience. */
6618 device->wined3d_device = ddraw->wined3d_device;
6619 wined3d_device_incref(ddraw->wined3d_device);
6620
6621 /* Render to the back buffer */
6622 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6623 if (FAILED(hr))
6624 {
6625 ERR("Failed to set render target, hr %#x.\n", hr);
6626 wined3d_buffer_decref(device->indexbuffer);
6627 ddraw_handle_table_destroy(&device->handle_table);
6628 return hr;
6629 }
6630
6631 /* FIXME: This is broken. The target AddRef() makes some sense, because
6632 * we store a pointer during initialization, but then that's also where
6633 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6634 /* AddRef the render target. Also AddRef the render target from ddraw,
6635 * because if it is released before the app releases the D3D device, the
6636 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6637 *
6638 * In most cases, those surfaces are the same anyway, but this will simply
6639 * add another ref which is released when the device is destroyed. */
6640 if (version != 1)
6641 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6642
6643 ddraw->d3ddevice = device;
6644
6645 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6646 d3d_device_update_depth_stencil(device));
6647 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6648 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6649
6650 return D3D_OK;
6651 }
6652
6653 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
6654 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6655 {
6656 struct d3d_device *object;
6657 HRESULT hr;
6658
6659 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6660 ddraw, target, version, device, outer_unknown);
6661
6662 if (DefaultSurfaceType != WINED3D_SURFACE_TYPE_OPENGL)
6663 {
6664 ERR_(winediag)("The application wants to create a Direct3D device, "
6665 "but the current DirectDrawRenderer does not support this.\n");
6666
6667 return DDERR_NO3D;
6668 }
6669
6670 if (ddraw->d3ddevice)
6671 {
6672 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6673 return DDERR_INVALIDPARAMS;
6674 }
6675
6676 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6677 if (!object)
6678 {
6679 ERR("Failed to allocate device memory.\n");
6680 return DDERR_OUTOFMEMORY;
6681 }
6682
6683 hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
6684 if (FAILED(hr))
6685 {
6686 WARN("Failed to initialize device, hr %#x.\n", hr);
6687 HeapFree(GetProcessHeap(), 0, object);
6688 return hr;
6689 }
6690
6691 TRACE("Created device %p.\n", object);
6692 *device = object;
6693
6694 return D3D_OK;
6695 }