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