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