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