ReactOS 0.4.16-dev-38-g96c65e9
device.c
Go to the documentation of this file.
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
37
38/* The device ID */
40 0xaef72d43,
41 0xb09a,
42 0x4b7b,
43 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
44};
45
46static 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
55static 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
74
75 return oldcw;
76}
77
78static inline struct d3d_device *impl_from_IUnknown(IUnknown *iface)
79{
80 return CONTAINING_RECORD(iface, struct d3d_device, IUnknown_inner);
81}
82
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;
93 }
94
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
141static HRESULT WINAPI d3d_device7_QueryInterface(IDirect3DDevice7 *iface, REFIID riid, void **out)
142{
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
150static HRESULT WINAPI d3d_device3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid, void **out)
151{
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
159static HRESULT WINAPI d3d_device2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid, void **out)
160{
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
168static HRESULT WINAPI d3d_device1_QueryInterface(IDirect3DDevice *iface, REFIID riid, void **out)
169{
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
178{
179 struct d3d_device *device = impl_from_IUnknown(iface);
181
182 TRACE("%p increasing refcount to %u.\n", device, ref);
183
184 return ref;
185}
186
187static ULONG WINAPI d3d_device7_AddRef(IDirect3DDevice7 *iface)
188{
190
191 TRACE("iface %p.\n", iface);
192
193 return IUnknown_AddRef(device->outer_unknown);
194}
195
196static ULONG WINAPI d3d_device3_AddRef(IDirect3DDevice3 *iface)
197{
199
200 TRACE("iface %p.\n", iface);
201
202 return IUnknown_AddRef(device->outer_unknown);
203}
204
205static ULONG WINAPI d3d_device2_AddRef(IDirect3DDevice2 *iface)
206{
208
209 TRACE("iface %p.\n", iface);
210
211 return IUnknown_AddRef(device->outer_unknown);
212}
213
214static ULONG WINAPI d3d_device1_AddRef(IDirect3DDevice *iface)
215{
217
218 TRACE("iface %p.\n", iface);
219
220 return IUnknown_AddRef(device->outer_unknown);
221}
222
224{
225 struct d3d_device *This = impl_from_IUnknown(iface);
228
229 TRACE("%p decreasing refcount to %u.\n", This, ref);
230
231 /* This method doesn't destroy the wined3d device, because it's still in
232 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
233 * wined3d device when the render target is released. */
234 if (!ref)
235 {
236 DWORD i;
237 struct list *vp_entry, *vp_entry2;
238
240
241 /* There is no need to unset any resources here, wined3d will take
242 * care of that on uninit_3d(). */
243
244 if (This->index_buffer)
245 wined3d_buffer_decref(This->index_buffer);
246 if (This->vertex_buffer)
247 wined3d_buffer_decref(This->vertex_buffer);
248
250
251 /* Release the wined3d device. This won't destroy it. */
252 if (!wined3d_device_decref(This->wined3d_device))
253 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
254
255 /* The texture handles should be unset by now, but there might be some bits
256 * missing in our reference counting(needs test). Do a sanity check. */
257 for (i = 0; i < This->handle_table.entry_count; ++i)
258 {
259 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
260
261 switch (entry->type)
262 {
264 break;
265
267 {
268 struct d3d_material *m = entry->object;
269 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
270 m->Handle = 0;
271 break;
272 }
273
275 {
276 /* No FIXME here because this might happen because of sloppy applications. */
277 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
278 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
279 break;
280 }
281
283 {
284 /* No FIXME here because this might happen because of sloppy applications. */
285 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
286 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
287 break;
288 }
289
291 {
292 struct ddraw_surface *surf = entry->object;
293 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
294 surf->Handle = 0;
295 break;
296 }
297
298 default:
299 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
300 break;
301 }
302 }
303
304 ddraw_handle_table_destroy(&This->handle_table);
305
306 LIST_FOR_EACH_SAFE(vp_entry, vp_entry2, &This->viewport_list)
307 {
308 struct d3d_viewport *vp = LIST_ENTRY(vp_entry, struct d3d_viewport, entry);
309 IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
310 }
311
312 TRACE("Releasing render target %p.\n", This->rt_iface);
313 rt_iface = This->rt_iface;
314 This->rt_iface = NULL;
315 if (This->version != 1)
316 IUnknown_Release(rt_iface);
317 TRACE("Render target release done.\n");
318
319 /* Releasing the render target above may have released the last
320 * reference to the ddraw object. */
321 if (This->ddraw)
322 This->ddraw->d3ddevice = NULL;
323
324 /* Now free the structure */
327 }
328
329 TRACE("Done\n");
330 return ref;
331}
332
333static ULONG WINAPI d3d_device7_Release(IDirect3DDevice7 *iface)
334{
336
337 TRACE("iface %p.\n", iface);
338
339 return IUnknown_Release(device->outer_unknown);
340}
341
342static ULONG WINAPI d3d_device3_Release(IDirect3DDevice3 *iface)
343{
345
346 TRACE("iface %p.\n", iface);
347
348 return IUnknown_Release(device->outer_unknown);
349}
350
351static ULONG WINAPI d3d_device2_Release(IDirect3DDevice2 *iface)
352{
354
355 TRACE("iface %p.\n", iface);
356
357 return IUnknown_Release(device->outer_unknown);
358}
359
360static ULONG WINAPI d3d_device1_Release(IDirect3DDevice *iface)
361{
363
364 TRACE("iface %p.\n", iface);
365
366 return IUnknown_Release(device->outer_unknown);
367}
368
369/*****************************************************************************
370 * IDirect3DDevice Methods
371 *****************************************************************************/
372
373/*****************************************************************************
374 * IDirect3DDevice::Initialize
375 *
376 * Initializes a Direct3DDevice. This implementation is a no-op, as all
377 * initialization is done at create time.
378 *
379 * Exists in Version 1
380 *
381 * Parameters:
382 * No idea what they mean, as the MSDN page is gone
383 *
384 * Returns: DD_OK
385 *
386 *****************************************************************************/
387static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface,
388 IDirect3D *d3d, GUID *guid, D3DDEVICEDESC *device_desc)
389{
390 /* It shouldn't be crucial, but print a FIXME, I'm interested if
391 * any game calls it and when. */
392 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
393 iface, d3d, debugstr_guid(guid), device_desc);
394
395 return D3D_OK;
396}
397
398static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *device_desc)
399{
401
402 TRACE("iface %p, device_desc %p.\n", iface, device_desc);
403
404 if (!device_desc)
405 {
406 WARN("device_desc is NULL, returning DDERR_INVALIDPARAMS.\n");
407 return DDERR_INVALIDPARAMS;
408 }
409
410 /* Call the same function used by IDirect3D, this saves code */
411 return ddraw_get_d3dcaps(device->ddraw, device_desc);
412}
413
415{
416 return d3d_device7_GetCaps(iface, desc);
417}
418
420{
421 HRESULT hr;
422 WORD old_fpucw;
423
424 old_fpucw = d3d_fpu_setup();
425 hr = d3d_device7_GetCaps(iface, desc);
426 set_fpu_control_word(old_fpucw);
427
428 return hr;
429}
430/*****************************************************************************
431 * IDirect3DDevice3::GetCaps
432 *
433 * Retrieves the capabilities of the hardware device and the emulation
434 * device. For Wine, hardware and emulation are the same (it's all HW).
435 *
436 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
437 *
438 * Parameters:
439 * HWDesc: Structure to fill with the HW caps
440 * HelDesc: Structure to fill with the hardware emulation caps
441 *
442 * Returns:
443 * D3D_OK on success
444 * D3DERR_* if a problem occurs. See WineD3D
445 *
446 *****************************************************************************/
447
448/* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
449 * Microsoft just expanded the existing structure without naming them
450 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
451 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
452 * one with 252 bytes.
453 *
454 * All 3 versions are allowed as parameters and only the specified amount of
455 * bytes is written.
456 *
457 * Note that Direct3D7 and earlier are not available in native Win64
458 * ddraw.dll builds, so possible size differences between 32 bit and
459 * 64 bit are a non-issue.
460 */
462{
463 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
464 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
465 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
466 return FALSE;
467}
468
469static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
470 D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc)
471{
473 D3DDEVICEDESC7 desc7;
474 D3DDEVICEDESC desc1;
475 HRESULT hr;
476
477 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
478
479 if (!HWDesc)
480 {
481 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
482 return DDERR_INVALIDPARAMS;
483 }
484 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
485 {
486 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
487 return DDERR_INVALIDPARAMS;
488 }
489 if (!HelDesc)
490 {
491 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
492 return DDERR_INVALIDPARAMS;
493 }
494 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
495 {
496 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
497 return DDERR_INVALIDPARAMS;
498 }
499
500 if (FAILED(hr = ddraw_get_d3dcaps(device->ddraw, &desc7)))
501 return hr;
502
503 ddraw_d3dcaps1_from_7(&desc1, &desc7);
504 DD_STRUCT_COPY_BYSIZE(HWDesc, &desc1);
505 DD_STRUCT_COPY_BYSIZE(HelDesc, &desc1);
506 return D3D_OK;
507}
508
509static HRESULT WINAPI d3d_device2_GetCaps(IDirect3DDevice2 *iface,
510 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
511{
513
514 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
515
516 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
517}
518
519static HRESULT WINAPI d3d_device1_GetCaps(IDirect3DDevice *iface,
520 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
521{
523
524 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
525
526 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
527}
528
529/*****************************************************************************
530 * IDirect3DDevice2::SwapTextureHandles
531 *
532 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
533 *
534 * Parameters:
535 * Tex1, Tex2: The 2 Textures to swap
536 *
537 * Returns:
538 * D3D_OK
539 *
540 *****************************************************************************/
541static HRESULT WINAPI d3d_device2_SwapTextureHandles(IDirect3DDevice2 *iface,
542 IDirect3DTexture2 *tex1, IDirect3DTexture2 *tex2)
543{
547 DWORD h1, h2;
548
549 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
550
552
553 h1 = surf1->Handle - 1;
554 h2 = surf2->Handle - 1;
555 device->handle_table.entries[h1].object = surf2;
556 device->handle_table.entries[h2].object = surf1;
557 surf2->Handle = h1 + 1;
558 surf1->Handle = h2 + 1;
559
561
562 return D3D_OK;
563}
564
565static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface,
566 IDirect3DTexture *tex1, IDirect3DTexture *tex2)
567{
571 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
572 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
573
574 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
575
576 return d3d_device2_SwapTextureHandles(&device->IDirect3DDevice2_iface, t1, t2);
577}
578
579/*****************************************************************************
580 * IDirect3DDevice3::GetStats
581 *
582 * This method seems to retrieve some stats from the device.
583 * The MSDN documentation doesn't exist any more, but the D3DSTATS
584 * structure suggests that the amount of drawn primitives and processed
585 * vertices is returned.
586 *
587 * Exists in Version 1, 2 and 3
588 *
589 * Parameters:
590 * Stats: Pointer to a D3DSTATS structure to be filled
591 *
592 * Returns:
593 * D3D_OK on success
594 * DDERR_INVALIDPARAMS if Stats == NULL
595 *
596 *****************************************************************************/
597static HRESULT WINAPI d3d_device3_GetStats(IDirect3DDevice3 *iface, D3DSTATS *Stats)
598{
599 FIXME("iface %p, stats %p stub!\n", iface, Stats);
600
601 if(!Stats)
602 return DDERR_INVALIDPARAMS;
603
604 /* Fill the Stats with 0 */
605 Stats->dwTrianglesDrawn = 0;
606 Stats->dwLinesDrawn = 0;
607 Stats->dwPointsDrawn = 0;
608 Stats->dwSpansDrawn = 0;
609 Stats->dwVerticesProcessed = 0;
610
611 return D3D_OK;
612}
613
614static HRESULT WINAPI d3d_device2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *stats)
615{
617
618 TRACE("iface %p, stats %p.\n", iface, stats);
619
620 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
621}
622
623static HRESULT WINAPI d3d_device1_GetStats(IDirect3DDevice *iface, D3DSTATS *stats)
624{
626
627 TRACE("iface %p, stats %p.\n", iface, stats);
628
629 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
630}
631
632/*****************************************************************************
633 * IDirect3DDevice::CreateExecuteBuffer
634 *
635 * Creates an IDirect3DExecuteBuffer, used for rendering with a
636 * Direct3DDevice.
637 *
638 * Version 1 only.
639 *
640 * Params:
641 * Desc: Buffer description
642 * ExecuteBuffer: Address to return the Interface pointer at
643 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
644 * support
645 *
646 * Returns:
647 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
648 * DDERR_OUTOFMEMORY if we ran out of memory
649 * D3D_OK on success
650 *
651 *****************************************************************************/
652static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface,
653 D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown)
654{
657 HRESULT hr;
658
659 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
660 iface, buffer_desc, ExecuteBuffer, outer_unknown);
661
662 if (outer_unknown)
664
665 /* Allocate the new Execute Buffer */
666 if (!(object = heap_alloc_zero(sizeof(*object))))
667 {
668 ERR("Failed to allocate execute buffer memory.\n");
669 return DDERR_OUTOFMEMORY;
670 }
671
672 hr = d3d_execute_buffer_init(object, device, buffer_desc);
673 if (FAILED(hr))
674 {
675 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
676 heap_free(object);
677 return hr;
678 }
679
680 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
681
682 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
683
684 return D3D_OK;
685}
686
687/*****************************************************************************
688 * IDirect3DDevice::Execute
689 *
690 * Executes all the stuff in an execute buffer.
691 *
692 * Params:
693 * ExecuteBuffer: The buffer to execute
694 * Viewport: The viewport used for rendering
695 * Flags: Some flags
696 *
697 * Returns:
698 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
699 * D3D_OK on success
700 *
701 *****************************************************************************/
702static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface,
703 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags)
704{
707 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport);
708 HRESULT hr;
709
710 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags);
711
712 if(!buffer)
713 return DDERR_INVALIDPARAMS;
714
715 /* Execute... */
717 hr = d3d_execute_buffer_execute(buffer, device, viewport_impl);
719
720 return hr;
721}
722
723/*****************************************************************************
724 * IDirect3DDevice3::AddViewport
725 *
726 * Add a Direct3DViewport to the device's viewport list. These viewports
727 * are wrapped to IDirect3DDevice7 viewports in viewport.c
728 *
729 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
730 * are the same interfaces.
731 *
732 * Params:
733 * Viewport: The viewport to add
734 *
735 * Returns:
736 * DDERR_INVALIDPARAMS if Viewport == NULL
737 * D3D_OK on success
738 *
739 *****************************************************************************/
740static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
741{
744
745 TRACE("iface %p, viewport %p.\n", iface, viewport);
746
747 /* Sanity check */
748 if(!vp)
749 return DDERR_INVALIDPARAMS;
750
753 list_add_head(&device->viewport_list, &vp->entry);
754 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
755 vp->active_device = device;
757
758 return D3D_OK;
759}
760
761static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
762 IDirect3DViewport2 *viewport)
763{
766
767 TRACE("iface %p, viewport %p.\n", iface, viewport);
768
769 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
770}
771
772static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
773{
776
777 TRACE("iface %p, viewport %p.\n", iface, viewport);
778
779 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
780}
781
782/*****************************************************************************
783 * IDirect3DDevice3::DeleteViewport
784 *
785 * Deletes a Direct3DViewport from the device's viewport list.
786 *
787 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
788 * are equal.
789 *
790 * Params:
791 * Viewport: The viewport to delete
792 *
793 * Returns:
794 * D3D_OK on success
795 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
796 *
797 *****************************************************************************/
798static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
799{
802
803 TRACE("iface %p, viewport %p.\n", iface, viewport);
804
805 if (!vp)
806 {
807 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n");
808 return DDERR_INVALIDPARAMS;
809 }
810
812
813 if (vp->active_device != device)
814 {
815 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
817 return DDERR_INVALIDPARAMS;
818 }
819
820 if (device->current_viewport == vp)
821 {
822 TRACE("Deleting current viewport, unsetting and releasing\n");
824 device->current_viewport = NULL;
825 }
826
827 vp->active_device = NULL;
828 list_remove(&vp->entry);
829
831
833
834 return D3D_OK;
835}
836
837static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
838{
841
842 TRACE("iface %p, viewport %p.\n", iface, viewport);
843
844 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
845 vp ? &vp->IDirect3DViewport3_iface : NULL);
846}
847
848static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
849{
852
853 TRACE("iface %p, viewport %p.\n", iface, viewport);
854
855 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
856 vp ? &vp->IDirect3DViewport3_iface : NULL);
857}
858
859/*****************************************************************************
860 * IDirect3DDevice3::NextViewport
861 *
862 * Returns a viewport from the viewport list, depending on the
863 * passed viewport and the flags.
864 *
865 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
866 * are equal.
867 *
868 * Params:
869 * Viewport: Viewport to use for beginning the search
870 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
871 *
872 * Returns:
873 * D3D_OK on success
874 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
875 *
876 *****************************************************************************/
877static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
878 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
879{
882 struct d3d_viewport *next;
883 struct list *entry;
884
885 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
886 iface, Viewport3, lplpDirect3DViewport3, flags);
887
888 if(!vp)
889 {
890 *lplpDirect3DViewport3 = NULL;
891 return DDERR_INVALIDPARAMS;
892 }
893
894
896 switch (flags)
897 {
898 case D3DNEXT_NEXT:
899 entry = list_next(&This->viewport_list, &vp->entry);
900 break;
901
902 case D3DNEXT_HEAD:
903 entry = list_head(&This->viewport_list);
904 break;
905
906 case D3DNEXT_TAIL:
907 entry = list_tail(&This->viewport_list);
908 break;
909
910 default:
911 WARN("Invalid flags %#x.\n", flags);
912 *lplpDirect3DViewport3 = NULL;
914 return DDERR_INVALIDPARAMS;
915 }
916
917 if (entry)
918 {
920 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
921 }
922 else
923 *lplpDirect3DViewport3 = NULL;
924
926
927 return D3D_OK;
928}
929
930static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
931 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
932{
935 IDirect3DViewport3 *res;
936 HRESULT hr;
937
938 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
939 iface, viewport, next, flags);
940
941 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
943 *next = (IDirect3DViewport2 *)res;
944 return hr;
945}
946
947static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
948 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
949{
952 IDirect3DViewport3 *res;
953 HRESULT hr;
954
955 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
956 iface, viewport, next, flags);
957
958 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
960 *next = (IDirect3DViewport *)res;
961 return hr;
962}
963
964/*****************************************************************************
965 * IDirect3DDevice::Pick
966 *
967 * Executes an execute buffer without performing rendering. Instead, a
968 * list of primitives that intersect with (x1,y1) of the passed rectangle
969 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
970 * this list.
971 *
972 * Version 1 only
973 *
974 * Params:
975 * ExecuteBuffer: Buffer to execute
976 * Viewport: Viewport to use for execution
977 * Flags: None are defined, according to the SDK
978 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
979 * x2 and y2 are ignored.
980 *
981 * Returns:
982 * D3D_OK because it's a stub
983 *
984 *****************************************************************************/
985static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
986 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
987{
988 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
989 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
990
991 return D3D_OK;
992}
993
994/*****************************************************************************
995 * IDirect3DDevice::GetPickRecords
996 *
997 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
998 *
999 * Version 1 only
1000 *
1001 * Params:
1002 * Count: Pointer to a DWORD containing the numbers of pick records to
1003 * retrieve
1004 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1005 *
1006 * Returns:
1007 * D3D_OK, because it's a stub
1008 *
1009 *****************************************************************************/
1010static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1011 DWORD *count, D3DPICKRECORD *records)
1012{
1013 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1014
1015 return D3D_OK;
1016}
1017
1018/*****************************************************************************
1019 * IDirect3DDevice7::EnumTextureformats
1020 *
1021 * Enumerates the supported texture formats. It checks against a list of all possible
1022 * formats to see if WineD3D supports it. If so, then it is passed to the app.
1023 *
1024 * This is for Version 7 and 3, older versions have a different
1025 * callback function and their own implementation
1026 *
1027 * Params:
1028 * Callback: Callback to call for each enumerated format
1029 * Arg: Argument to pass to the callback
1030 *
1031 * Returns:
1032 * D3D_OK on success
1033 * DDERR_INVALIDPARAMS if Callback == NULL
1034 *
1035 *****************************************************************************/
1036static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1038{
1041 HRESULT hr;
1042 unsigned int i;
1043
1044 static const enum wined3d_format_id FormatList[] =
1045 {
1046 /* 16 bit */
1051 /* 32 bit */
1054 /* 8 bit */
1057 /* FOURCC codes */
1063 };
1064
1065 static const enum wined3d_format_id BumpFormatList[] =
1066 {
1072 };
1073
1074 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1075
1076 if (!callback)
1077 return DDERR_INVALIDPARAMS;
1078
1080
1081 memset(&mode, 0, sizeof(mode));
1083 {
1085 WARN("Cannot get the current adapter format\n");
1086 return hr;
1087 }
1088
1089 for (i = 0; i < ARRAY_SIZE(FormatList); ++i)
1090 {
1092 mode.format_id, WINED3DUSAGE_TEXTURE, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1093 {
1094 DDPIXELFORMAT pformat;
1095
1096 memset(&pformat, 0, sizeof(pformat));
1097 pformat.dwSize = sizeof(pformat);
1098 ddrawformat_from_wined3dformat(&pformat, FormatList[i]);
1099
1100 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1101 hr = callback(&pformat, context);
1102 if(hr != DDENUMRET_OK)
1103 {
1104 TRACE("Format enumeration cancelled by application\n");
1106 return D3D_OK;
1107 }
1108 }
1109 }
1110
1111 for (i = 0; i < ARRAY_SIZE(BumpFormatList); ++i)
1112 {
1115 WINED3D_RTYPE_TEXTURE_2D, BumpFormatList[i]) == D3D_OK)
1116 {
1117 DDPIXELFORMAT pformat;
1118
1119 memset(&pformat, 0, sizeof(pformat));
1120 pformat.dwSize = sizeof(pformat);
1121 ddrawformat_from_wined3dformat(&pformat, BumpFormatList[i]);
1122
1123 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1124 hr = callback(&pformat, context);
1125 if(hr != DDENUMRET_OK)
1126 {
1127 TRACE("Format enumeration cancelled by application\n");
1129 return D3D_OK;
1130 }
1131 }
1132 }
1133 TRACE("End of enumeration\n");
1135
1136 return D3D_OK;
1137}
1138
1141{
1143}
1144
1147{
1148 HRESULT hr;
1149 WORD old_fpucw;
1150
1151 old_fpucw = d3d_fpu_setup();
1153 set_fpu_control_word(old_fpucw);
1154
1155 return hr;
1156}
1157
1158static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1160{
1162
1163 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1164
1165 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1166}
1167
1168/*****************************************************************************
1169 * IDirect3DDevice2::EnumTextureformats
1170 *
1171 * EnumTextureFormats for Version 1 and 2, see
1172 * IDirect3DDevice7::EnumTextureFormats for a more detailed description.
1173 *
1174 * This version has a different callback and does not enumerate FourCC
1175 * formats
1176 *
1177 *****************************************************************************/
1178static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1180{
1183 HRESULT hr;
1184 unsigned int i;
1185
1186 static const enum wined3d_format_id FormatList[] =
1187 {
1188 /* 16 bit */
1193 /* 32 bit */
1196 /* 8 bit */
1199 /* FOURCC codes - Not in this version*/
1200 };
1201
1202 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1203
1204 if (!callback)
1205 return DDERR_INVALIDPARAMS;
1206
1208
1209 memset(&mode, 0, sizeof(mode));
1211 {
1213 WARN("Cannot get the current adapter format\n");
1214 return hr;
1215 }
1216
1217 for (i = 0; i < ARRAY_SIZE(FormatList); ++i)
1218 {
1220 mode.format_id, WINED3DUSAGE_TEXTURE, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1221 {
1222 DDSURFACEDESC sdesc;
1223
1224 memset(&sdesc, 0, sizeof(sdesc));
1225 sdesc.dwSize = sizeof(sdesc);
1226 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1227 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1228 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1229 ddrawformat_from_wined3dformat(&sdesc.ddpfPixelFormat, FormatList[i]);
1230
1231 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1232 hr = callback(&sdesc, context);
1233 if(hr != DDENUMRET_OK)
1234 {
1235 TRACE("Format enumeration cancelled by application\n");
1237 return D3D_OK;
1238 }
1239 }
1240 }
1241 TRACE("End of enumeration\n");
1243
1244 return D3D_OK;
1245}
1246
1247static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1249{
1251
1252 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1253
1254 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1255}
1256
1257/*****************************************************************************
1258 * IDirect3DDevice::CreateMatrix
1259 *
1260 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1261 * allocated for the handle.
1262 *
1263 * Version 1 only
1264 *
1265 * Params
1266 * D3DMatHandle: Address to return the handle at
1267 *
1268 * Returns:
1269 * D3D_OK on success
1270 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1271 *
1272 *****************************************************************************/
1273static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1274{
1277 DWORD h;
1278
1279 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1280
1281 if(!D3DMatHandle)
1282 return DDERR_INVALIDPARAMS;
1283
1284 if (!(matrix = heap_alloc_zero(sizeof(*matrix))))
1285 {
1286 ERR("Out of memory when allocating a D3DMATRIX\n");
1287 return DDERR_OUTOFMEMORY;
1288 }
1289
1291
1293 if (h == DDRAW_INVALID_HANDLE)
1294 {
1295 ERR("Failed to allocate a matrix handle.\n");
1298 return DDERR_OUTOFMEMORY;
1299 }
1300
1301 *D3DMatHandle = h + 1;
1302
1303 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1304
1306
1307 return D3D_OK;
1308}
1309
1310/*****************************************************************************
1311 * IDirect3DDevice::SetMatrix
1312 *
1313 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1314 * allocated for the handle
1315 *
1316 * Version 1 only
1317 *
1318 * Params:
1319 * D3DMatHandle: Handle to set the matrix to
1320 * D3DMatrix: Matrix to set
1321 *
1322 * Returns:
1323 * D3D_OK on success
1324 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1325 * to set is NULL
1326 *
1327 *****************************************************************************/
1328static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1329 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1330{
1331 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1332 D3DMATRIX *m;
1333
1334 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1335
1336 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1337
1339
1340 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1341 if (!m)
1342 {
1343 WARN("Invalid matrix handle.\n");
1345 return DDERR_INVALIDPARAMS;
1346 }
1347
1348 if (TRACE_ON(ddraw))
1349 dump_D3DMATRIX(D3DMatrix);
1350
1351 *m = *D3DMatrix;
1352
1353 if (D3DMatHandle == This->world)
1354 wined3d_device_set_transform(This->wined3d_device,
1355 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1356
1357 if (D3DMatHandle == This->view)
1358 wined3d_device_set_transform(This->wined3d_device,
1359 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1360
1361 if (D3DMatHandle == This->proj)
1362 wined3d_device_set_transform(This->wined3d_device,
1363 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1364
1366
1367 return D3D_OK;
1368}
1369
1370/*****************************************************************************
1371 * IDirect3DDevice::GetMatrix
1372 *
1373 * Returns the content of a D3DMATRIX handle
1374 *
1375 * Version 1 only
1376 *
1377 * Params:
1378 * D3DMatHandle: Matrix handle to read the content from
1379 * D3DMatrix: Address to store the content at
1380 *
1381 * Returns:
1382 * D3D_OK on success
1383 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1384 *
1385 *****************************************************************************/
1386static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1387 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1388{
1390 D3DMATRIX *m;
1391
1392 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1393
1394 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1395
1397
1398 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1399 if (!m)
1400 {
1401 WARN("Invalid matrix handle.\n");
1403 return DDERR_INVALIDPARAMS;
1404 }
1405
1406 *D3DMatrix = *m;
1407
1409
1410 return D3D_OK;
1411}
1412
1413/*****************************************************************************
1414 * IDirect3DDevice::DeleteMatrix
1415 *
1416 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1417 *
1418 * Version 1 only
1419 *
1420 * Params:
1421 * D3DMatHandle: Handle to destroy
1422 *
1423 * Returns:
1424 * D3D_OK on success
1425 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1426 *
1427 *****************************************************************************/
1428static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1429{
1431 D3DMATRIX *m;
1432
1433 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1434
1436
1437 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1438 if (!m)
1439 {
1440 WARN("Invalid matrix handle.\n");
1442 return DDERR_INVALIDPARAMS;
1443 }
1444
1446
1447 heap_free(m);
1448
1449 return D3D_OK;
1450}
1451
1452/*****************************************************************************
1453 * IDirect3DDevice7::BeginScene
1454 *
1455 * This method must be called before any rendering is performed.
1456 * IDirect3DDevice::EndScene has to be called after the scene is complete
1457 *
1458 * Version 1, 2, 3 and 7
1459 *
1460 * Returns:
1461 * D3D_OK on success,
1462 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1463 * started scene).
1464 *
1465 *****************************************************************************/
1466static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1467{
1469 HRESULT hr;
1470
1471 TRACE("iface %p.\n", iface);
1472
1474 hr = wined3d_device_begin_scene(device->wined3d_device);
1476
1477 if(hr == WINED3D_OK) return D3D_OK;
1478 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1479}
1480
1481static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1482{
1483 return d3d_device7_BeginScene(iface);
1484}
1485
1487{
1488 HRESULT hr;
1489 WORD old_fpucw;
1490
1491 old_fpucw = d3d_fpu_setup();
1492 hr = d3d_device7_BeginScene(iface);
1493 set_fpu_control_word(old_fpucw);
1494
1495 return hr;
1496}
1497
1498static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1499{
1501
1502 TRACE("iface %p.\n", iface);
1503
1504 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1505}
1506
1507static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1508{
1510
1511 TRACE("iface %p.\n", iface);
1512
1513 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1514}
1515
1516static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1517{
1519
1520 TRACE("iface %p.\n", iface);
1521
1522 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1523}
1524
1525/*****************************************************************************
1526 * IDirect3DDevice7::EndScene
1527 *
1528 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1529 * This method must be called after rendering is finished.
1530 *
1531 * Version 1, 2, 3 and 7
1532 *
1533 * Returns:
1534 * D3D_OK on success,
1535 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1536 * that only if the scene was already ended.
1537 *
1538 *****************************************************************************/
1539static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1540{
1542 HRESULT hr;
1543
1544 TRACE("iface %p.\n", iface);
1545
1547 hr = wined3d_device_end_scene(device->wined3d_device);
1549
1550 if(hr == WINED3D_OK) return D3D_OK;
1551 else return D3DERR_SCENE_NOT_IN_SCENE;
1552}
1553
1555{
1556 return d3d_device7_EndScene(iface);
1557}
1558
1560{
1561 HRESULT hr;
1562 WORD old_fpucw;
1563
1564 old_fpucw = d3d_fpu_setup();
1565 hr = d3d_device7_EndScene(iface);
1566 set_fpu_control_word(old_fpucw);
1567
1568 return hr;
1569}
1570
1572{
1574
1575 TRACE("iface %p.\n", iface);
1576
1577 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1578}
1579
1581{
1583
1584 TRACE("iface %p.\n", iface);
1585
1586 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1587}
1588
1590{
1592
1593 TRACE("iface %p.\n", iface);
1594
1595 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1596}
1597
1598/*****************************************************************************
1599 * IDirect3DDevice7::GetDirect3D
1600 *
1601 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1602 * this device.
1603 *
1604 * Params:
1605 * Direct3D7: Address to store the interface pointer at
1606 *
1607 * Returns:
1608 * D3D_OK on success
1609 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1610 *
1611 *****************************************************************************/
1612static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1613{
1615
1616 TRACE("iface %p, d3d %p.\n", iface, d3d);
1617
1618 if (!d3d)
1619 return DDERR_INVALIDPARAMS;
1620
1621 *d3d = &device->ddraw->IDirect3D7_iface;
1622 IDirect3D7_AddRef(*d3d);
1623
1624 TRACE("Returning interface %p.\n", *d3d);
1625 return D3D_OK;
1626}
1627
1628static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1629{
1631
1632 TRACE("iface %p, d3d %p.\n", iface, d3d);
1633
1634 if (!d3d)
1635 return DDERR_INVALIDPARAMS;
1636
1637 *d3d = &device->ddraw->IDirect3D3_iface;
1638 IDirect3D3_AddRef(*d3d);
1639
1640 TRACE("Returning interface %p.\n", *d3d);
1641 return D3D_OK;
1642}
1643
1644static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1645{
1647
1648 TRACE("iface %p, d3d %p.\n", iface, d3d);
1649
1650 if (!d3d)
1651 return DDERR_INVALIDPARAMS;
1652
1653 *d3d = &device->ddraw->IDirect3D2_iface;
1654 IDirect3D2_AddRef(*d3d);
1655
1656 TRACE("Returning interface %p.\n", *d3d);
1657 return D3D_OK;
1658}
1659
1660static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1661{
1663
1664 TRACE("iface %p, d3d %p.\n", iface, d3d);
1665
1666 if (!d3d)
1667 return DDERR_INVALIDPARAMS;
1668
1669 *d3d = &device->ddraw->IDirect3D_iface;
1670 IDirect3D_AddRef(*d3d);
1671
1672 TRACE("Returning interface %p.\n", *d3d);
1673 return D3D_OK;
1674}
1675
1676/*****************************************************************************
1677 * IDirect3DDevice3::SetCurrentViewport
1678 *
1679 * Sets a Direct3DViewport as the current viewport.
1680 * For the thunks note that all viewport interface versions are equal
1681 *
1682 * Params:
1683 * Direct3DViewport3: The viewport to set
1684 *
1685 * Version 2 and 3
1686 *
1687 * Returns:
1688 * D3D_OK on success
1689 * (Is a NULL viewport valid?)
1690 *
1691 *****************************************************************************/
1692static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1693{
1695 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1696
1697 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1698
1699 if (!vp)
1700 {
1701 WARN("Direct3DViewport3 is NULL, returning DDERR_INVALIDPARAMS\n");
1702 return DDERR_INVALIDPARAMS;
1703 }
1704
1706 /* Do nothing if the specified viewport is the same as the current one */
1707 if (This->current_viewport == vp)
1708 {
1710 return D3D_OK;
1711 }
1712
1713 if (vp->active_device != This)
1714 {
1715 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1717 return DDERR_INVALIDPARAMS;
1718 }
1719
1720 /* Release previous viewport and AddRef the new one */
1721 if (This->current_viewport)
1722 {
1723 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1724 &This->current_viewport->IDirect3DViewport3_iface);
1725 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1726 }
1727 IDirect3DViewport3_AddRef(Direct3DViewport3);
1728
1729 /* Set this viewport as the current viewport */
1730 This->current_viewport = vp;
1731
1732 /* Activate this viewport */
1733 viewport_activate(This->current_viewport, FALSE);
1734
1736
1737 return D3D_OK;
1738}
1739
1740static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1741{
1744
1745 TRACE("iface %p, viewport %p.\n", iface, viewport);
1746
1747 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface,
1748 vp ? &vp->IDirect3DViewport3_iface : NULL);
1749}
1750
1751/*****************************************************************************
1752 * IDirect3DDevice3::GetCurrentViewport
1753 *
1754 * Returns the currently active viewport.
1755 *
1756 * Version 2 and 3
1757 *
1758 * Params:
1759 * Direct3DViewport3: Address to return the interface pointer at
1760 *
1761 * Returns:
1762 * D3D_OK on success
1763 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1764 *
1765 *****************************************************************************/
1766static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1767{
1769
1770 TRACE("iface %p, viewport %p.\n", iface, viewport);
1771
1773 if (!device->current_viewport)
1774 {
1776 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n");
1778 }
1779
1780 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1781 IDirect3DViewport3_AddRef(*viewport);
1782
1783 TRACE("Returning interface %p.\n", *viewport);
1785 return D3D_OK;
1786}
1787
1788static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1789{
1791
1792 TRACE("iface %p, viewport %p.\n", iface, viewport);
1793
1794 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1795 (IDirect3DViewport3 **)viewport);
1796}
1797
1799{
1801 || surface->palette;
1802}
1803
1806{
1807 HRESULT hr;
1808
1809 if (device->rt_iface == rt_iface)
1810 {
1811 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1812 return D3D_OK;
1813 }
1814 if (!target)
1815 {
1816 WARN("Trying to set render target to NULL.\n");
1817 return DDERR_INVALIDPARAMS;
1818 }
1819
1822 return hr;
1823
1824 IUnknown_AddRef(rt_iface);
1825 IUnknown_Release(device->rt_iface);
1826 device->rt_iface = rt_iface;
1828
1829 return D3D_OK;
1830}
1831
1832static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1834{
1837 HRESULT hr;
1838
1839 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1840
1842
1843 if (!validate_surface_palette(target_impl))
1844 {
1845 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1847 return DDERR_INVALIDCAPS;
1848 }
1849
1850 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1851 {
1852 WARN("Surface %p is not a render target.\n", target_impl);
1854 return DDERR_INVALIDCAPS;
1855 }
1856
1857 if (device->hw && !(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1858 {
1859 WARN("Surface %p is not in video memory.\n", target_impl);
1861 return DDERR_INVALIDPARAMS;
1862 }
1863
1864 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1865 {
1866 WARN("Surface %p is a depth buffer.\n", target_impl);
1867 IDirectDrawSurface7_AddRef(target);
1868 IUnknown_Release(device->rt_iface);
1869 device->rt_iface = (IUnknown *)target;
1872 }
1873
1876 return hr;
1877}
1878
1880 IDirectDrawSurface7 *NewTarget, DWORD flags)
1881{
1882 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1883}
1884
1886 IDirectDrawSurface7 *NewTarget, DWORD flags)
1887{
1888 HRESULT hr;
1889 WORD old_fpucw;
1890
1891 old_fpucw = d3d_fpu_setup();
1892 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1893 set_fpu_control_word(old_fpucw);
1894
1895 return hr;
1896}
1897
1898static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1899 IDirectDrawSurface4 *target, DWORD flags)
1900{
1903 HRESULT hr;
1904
1905 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1906
1908
1909 if (!validate_surface_palette(target_impl))
1910 {
1911 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1913 return DDERR_INVALIDCAPS;
1914 }
1915
1916 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1917 {
1918 WARN("Surface %p is not a render target.\n", target_impl);
1920 return DDERR_INVALIDCAPS;
1921 }
1922
1923 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1924 {
1925 WARN("Surface %p is a depth buffer.\n", target_impl);
1926 IDirectDrawSurface4_AddRef(target);
1927 IUnknown_Release(device->rt_iface);
1928 device->rt_iface = (IUnknown *)target;
1931 }
1932
1933 if (device->hw && !(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1934 {
1935 WARN("Surface %p is not in video memory.\n", target_impl);
1936 IDirectDrawSurface4_AddRef(target);
1937 IUnknown_Release(device->rt_iface);
1938 device->rt_iface = (IUnknown *)target;
1940 return D3D_OK;
1941 }
1942
1945 return hr;
1946}
1947
1948static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1949 IDirectDrawSurface *target, DWORD flags)
1950{
1953 HRESULT hr;
1954
1955 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1956
1958
1959 if (!validate_surface_palette(target_impl))
1960 {
1961 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1963 return DDERR_INVALIDCAPS;
1964 }
1965
1966 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1967 {
1968 WARN("Surface %p is not a render target.\n", target_impl);
1970 return DDERR_INVALIDCAPS;
1971 }
1972
1973 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1974 {
1975 WARN("Surface %p is a depth buffer.\n", target_impl);
1976 IUnknown_Release(device->rt_iface);
1977 device->rt_iface = (IUnknown *)target;
1980 }
1981
1982 if (device->hw && !(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1983 {
1984 WARN("Surface %p is not in video memory.\n", target_impl);
1985 IDirectDrawSurface_AddRef(target);
1986 IUnknown_Release(device->rt_iface);
1987 device->rt_iface = (IUnknown *)target;
1989 return D3D_OK;
1990 }
1991
1994 return hr;
1995}
1996
1997/*****************************************************************************
1998 * IDirect3DDevice7::GetRenderTarget
1999 *
2000 * Returns the current render target.
2001 * This is handled locally, because the WineD3D render target's parent
2002 * is an IParent
2003 *
2004 * Version 2, 3 and 7
2005 *
2006 * Params:
2007 * RenderTarget: Address to store the surface interface pointer
2008 *
2009 * Returns:
2010 * D3D_OK on success
2011 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2012 *
2013 *****************************************************************************/
2014static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
2015{
2017 HRESULT hr;
2018
2019 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2020
2021 if(!RenderTarget)
2022 return DDERR_INVALIDPARAMS;
2023
2025 hr = IUnknown_QueryInterface(device->rt_iface, &IID_IDirectDrawSurface7, (void **)RenderTarget);
2027
2028 return hr;
2029}
2030
2031static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
2032{
2034 IDirectDrawSurface7 *RenderTarget7;
2035 struct ddraw_surface *RenderTargetImpl;
2036 HRESULT hr;
2037
2038 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2039
2040 if(!RenderTarget)
2041 return DDERR_INVALIDPARAMS;
2042
2043 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2044 if(hr != D3D_OK) return hr;
2045 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2046 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2047 IDirectDrawSurface4_AddRef(*RenderTarget);
2048 IDirectDrawSurface7_Release(RenderTarget7);
2049 return D3D_OK;
2050}
2051
2052static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
2053{
2055 IDirectDrawSurface7 *RenderTarget7;
2056 struct ddraw_surface *RenderTargetImpl;
2057 HRESULT hr;
2058
2059 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2060
2061 if(!RenderTarget)
2062 return DDERR_INVALIDPARAMS;
2063
2064 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2065 if(hr != D3D_OK) return hr;
2066 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2067 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2068 IDirectDrawSurface_AddRef(*RenderTarget);
2069 IDirectDrawSurface7_Release(RenderTarget7);
2070 return D3D_OK;
2071}
2072
2073/*****************************************************************************
2074 * IDirect3DDevice3::Begin
2075 *
2076 * Begins a description block of vertices. This is similar to glBegin()
2077 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2078 * described with IDirect3DDevice::Vertex are drawn.
2079 *
2080 * Version 2 and 3
2081 *
2082 * Params:
2083 * PrimitiveType: The type of primitives to draw
2084 * VertexTypeDesc: A flexible vertex format description of the vertices
2085 * Flags: Some flags..
2086 *
2087 * Returns:
2088 * D3D_OK on success
2089 *
2090 *****************************************************************************/
2091static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
2092 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
2093{
2095
2096 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
2097 iface, primitive_type, fvf, flags);
2098
2100 device->primitive_type = primitive_type;
2101 device->vertex_type = fvf;
2102 device->render_flags = flags;
2103 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
2104 device->nb_vertices = 0;
2106
2107 return D3D_OK;
2108}
2109
2110static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2112{
2114 DWORD fvf;
2115
2116 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2118
2119 switch (vertex_type)
2120 {
2121 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2122 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2123 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2124 default:
2125 ERR("Unexpected vertex type %#x.\n", vertex_type);
2126 return DDERR_INVALIDPARAMS; /* Should never happen */
2127 };
2128
2129 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2130}
2131
2132/*****************************************************************************
2133 * IDirect3DDevice3::BeginIndexed
2134 *
2135 * Draws primitives based on vertices in a vertex array which are specified
2136 * by indices.
2137 *
2138 * Version 2 and 3
2139 *
2140 * Params:
2141 * PrimitiveType: Primitive type to draw
2142 * VertexType: A FVF description of the vertex format
2143 * Vertices: pointer to an array containing the vertices
2144 * NumVertices: The number of vertices in the vertex array
2145 * Flags: Some flags ...
2146 *
2147 * Returns:
2148 * D3D_OK, because it's a stub
2149 *
2150 *****************************************************************************/
2151static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2153 void *vertices, DWORD vertex_count, DWORD flags)
2154{
2155 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2156 iface, primitive_type, fvf, vertices, vertex_count, flags);
2157
2158 return D3D_OK;
2159}
2160
2161
2162static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2164 void *vertices, DWORD vertex_count, DWORD flags)
2165{
2167 DWORD fvf;
2168
2169 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2170 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2171
2172 switch (vertex_type)
2173 {
2174 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2175 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2176 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2177 default:
2178 ERR("Unexpected vertex type %#x.\n", vertex_type);
2179 return DDERR_INVALIDPARAMS; /* Should never happen */
2180 };
2181
2182 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2183 primitive_type, fvf, vertices, vertex_count, flags);
2184}
2185
2186/*****************************************************************************
2187 * IDirect3DDevice3::Vertex
2188 *
2189 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2190 * drawn vertices in a vertex buffer. If the buffer is too small, its
2191 * size is increased.
2192 *
2193 * Version 2 and 3
2194 *
2195 * Params:
2196 * Vertex: Pointer to the vertex
2197 *
2198 * Returns:
2199 * D3D_OK, on success
2200 * DDERR_INVALIDPARAMS if Vertex is NULL
2201 *
2202 *****************************************************************************/
2203static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2204{
2206
2207 TRACE("iface %p, vertex %p.\n", iface, vertex);
2208
2209 if (!vertex)
2210 return DDERR_INVALIDPARAMS;
2211
2213 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2214 {
2215 BYTE *old_buffer;
2216
2217 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2218 old_buffer = device->sysmem_vertex_buffer;
2219 device->sysmem_vertex_buffer = heap_alloc(device->buffer_size);
2220 if (old_buffer)
2221 {
2222 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2223 heap_free(old_buffer);
2224 }
2225 }
2226
2227 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2229
2230 return D3D_OK;
2231}
2232
2233static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2234{
2236
2237 TRACE("iface %p, vertex %p.\n", iface, vertex);
2238
2239 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2240}
2241
2242/*****************************************************************************
2243 * IDirect3DDevice3::Index
2244 *
2245 * Specifies an index to a vertex to be drawn. The vertex array has to
2246 * be specified with BeginIndexed first.
2247 *
2248 * Parameters:
2249 * VertexIndex: The index of the vertex to draw
2250 *
2251 * Returns:
2252 * D3D_OK because it's a stub
2253 *
2254 *****************************************************************************/
2255static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2256{
2257 FIXME("iface %p, index %#x stub!\n", iface, index);
2258
2259 return D3D_OK;
2260}
2261
2262static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2263{
2265
2266 TRACE("iface %p, index %#x.\n", iface, index);
2267
2268 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2269}
2270
2271/*****************************************************************************
2272 * IDirect3DDevice7::GetRenderState
2273 *
2274 * Returns the value of a render state. The possible render states are
2275 * defined in include/d3dtypes.h
2276 *
2277 * Version 2, 3 and 7
2278 *
2279 * Params:
2280 * RenderStateType: Render state to return the current setting of
2281 * Value: Address to store the value at
2282 *
2283 * Returns:
2284 * D3D_OK on success,
2285 * DDERR_INVALIDPARAMS if Value == NULL
2286 *
2287 *****************************************************************************/
2288static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2290{
2292 HRESULT hr = D3D_OK;
2293
2294 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2295
2296 if (!value)
2297 return DDERR_INVALIDPARAMS;
2298
2300 switch (state)
2301 {
2303 {
2304 enum wined3d_texture_filter_type tex_mag;
2305
2307 switch (tex_mag)
2308 {
2309 case WINED3D_TEXF_POINT:
2311 break;
2314 break;
2315 default:
2316 ERR("Unhandled texture mag %d !\n",tex_mag);
2317 *value = 0;
2318 }
2319 break;
2320 }
2321
2323 {
2324 enum wined3d_texture_filter_type tex_min;
2325 enum wined3d_texture_filter_type tex_mip;
2326
2329 switch (tex_min)
2330 {
2331 case WINED3D_TEXF_POINT:
2332 switch (tex_mip)
2333 {
2334 case WINED3D_TEXF_NONE:
2336 break;
2337 case WINED3D_TEXF_POINT:
2339 break;
2342 break;
2343 default:
2344 ERR("Unhandled mip filter %#x.\n", tex_mip);
2346 break;
2347 }
2348 break;
2350 switch (tex_mip)
2351 {
2352 case WINED3D_TEXF_NONE:
2354 break;
2355 case WINED3D_TEXF_POINT:
2357 break;
2360 break;
2361 default:
2362 ERR("Unhandled mip filter %#x.\n", tex_mip);
2364 break;
2365 }
2366 break;
2367 default:
2368 ERR("Unhandled texture min filter %#x.\n",tex_min);
2370 break;
2371 }
2372 break;
2373 }
2374
2378 break;
2381 break;
2382
2384 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2385 hr = E_NOTIMPL;
2386 break;
2387
2390 WARN("Render state %#x is invalid in d3d7.\n", state);
2392 break;
2393
2396 break;
2397
2398 default:
2401 {
2402 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2403 hr = E_NOTIMPL;
2404 break;
2405 }
2407 }
2409
2410 return hr;
2411}
2412
2415{
2416 return d3d_device7_GetRenderState(iface, state, value);
2417}
2418
2421{
2422 HRESULT hr;
2423 WORD old_fpucw;
2424
2425 old_fpucw = d3d_fpu_setup();
2427 set_fpu_control_word(old_fpucw);
2428
2429 return hr;
2430}
2431
2432static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2434{
2436
2437 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2438
2439 switch (state)
2440 {
2442 {
2443 /* This state is wrapped to SetTexture in SetRenderState, so
2444 * it has to be wrapped to GetTexture here. */
2445 struct wined3d_texture *tex = NULL;
2446 *value = 0;
2447
2449 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2450 {
2451 /* The parent of the texture is the IDirectDrawSurface7
2452 * interface of the ddraw surface. */
2454 if (parent)
2455 *value = parent->root->Handle;
2456 }
2458
2459 return D3D_OK;
2460 }
2461
2463 {
2464 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2465 the mapping to get the value. */
2466 DWORD colorop, colorarg1, colorarg2;
2467 DWORD alphaop, alphaarg1, alphaarg2;
2468
2470
2471 device->legacyTextureBlending = TRUE;
2472
2479
2480 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2481 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2483 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2484 && alphaop == WINED3D_TOP_MODULATE
2485 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2487 else if (colorop == WINED3D_TOP_MODULATE
2488 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2489 && alphaop == WINED3D_TOP_MODULATE
2490 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2492 else
2493 {
2494 struct wined3d_texture *tex = NULL;
2495 BOOL tex_alpha = FALSE;
2496 DDPIXELFORMAT ddfmt;
2497
2498 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2499 {
2501
2503 ddfmt.dwSize = sizeof(ddfmt);
2504 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2505 if (ddfmt.u5.dwRGBAlphaBitMask)
2506 tex_alpha = TRUE;
2507 }
2508
2509 if (!(colorop == WINED3D_TOP_MODULATE
2510 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2511 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2512 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2513 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2514
2516 }
2517
2519
2520 return D3D_OK;
2521 }
2522
2526 *value = 0xffffffff;
2527 return D3D_OK;
2528
2529 default:
2530 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2531 }
2532}
2533
2534static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2536{
2538
2539 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2540
2541 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2542}
2543
2544/*****************************************************************************
2545 * IDirect3DDevice7::SetRenderState
2546 *
2547 * Sets a render state. The possible render states are defined in
2548 * include/d3dtypes.h
2549 *
2550 * Version 2, 3 and 7
2551 *
2552 * Params:
2553 * RenderStateType: State to set
2554 * Value: Value to assign to that state
2555 *
2556 *****************************************************************************/
2557static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2559{
2561 HRESULT hr = D3D_OK;
2562
2563 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2564
2566 /* Some render states need special care */
2567 switch (state)
2568 {
2569 /*
2570 * The ddraw texture filter mapping works like this:
2571 * D3DFILTER_NEAREST Point min/mag, no mip
2572 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2573 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2574 *
2575 * D3DFILTER_LINEAR Linear min/mag, no mip
2576 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2577 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2578 *
2579 * This is the opposite of the GL naming convention,
2580 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2581 */
2583 {
2584 enum wined3d_texture_filter_type tex_mag;
2585
2586 switch (value)
2587 {
2588 case D3DFILTER_NEAREST:
2591 tex_mag = WINED3D_TEXF_POINT;
2592 break;
2593 case D3DFILTER_LINEAR:
2596 tex_mag = WINED3D_TEXF_LINEAR;
2597 break;
2598 default:
2599 tex_mag = WINED3D_TEXF_POINT;
2600 FIXME("Unhandled texture mag %#x.\n", value);
2601 break;
2602 }
2603
2605 break;
2606 }
2607
2609 {
2610 enum wined3d_texture_filter_type tex_min;
2611 enum wined3d_texture_filter_type tex_mip;
2612
2613 switch (value)
2614 {
2615 case D3DFILTER_NEAREST:
2616 tex_min = WINED3D_TEXF_POINT;
2617 tex_mip = WINED3D_TEXF_NONE;
2618 break;
2619 case D3DFILTER_LINEAR:
2620 tex_min = WINED3D_TEXF_LINEAR;
2621 tex_mip = WINED3D_TEXF_NONE;
2622 break;
2624 tex_min = WINED3D_TEXF_POINT;
2625 tex_mip = WINED3D_TEXF_POINT;
2626 break;
2628 tex_min = WINED3D_TEXF_LINEAR;
2629 tex_mip = WINED3D_TEXF_POINT;
2630 break;
2632 tex_min = WINED3D_TEXF_POINT;
2633 tex_mip = WINED3D_TEXF_LINEAR;
2634 break;
2636 tex_min = WINED3D_TEXF_LINEAR;
2637 tex_mip = WINED3D_TEXF_LINEAR;
2638 break;
2639
2640 default:
2641 FIXME("Unhandled texture min %#x.\n",value);
2642 tex_min = WINED3D_TEXF_POINT;
2643 tex_mip = WINED3D_TEXF_NONE;
2644 break;
2645 }
2646
2648 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2650 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2651 break;
2652 }
2653
2657 /* Drop through */
2661 break;
2665 break;
2666
2668 /* This should probably just forward to the corresponding sampler
2669 * state. Needs tests. */
2670 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2671 hr = E_NOTIMPL;
2672 break;
2673
2676 WARN("Render state %#x is invalid in d3d7.\n", state);
2678 break;
2679
2682 break;
2683
2684 default:
2687 {
2688 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2689 hr = E_NOTIMPL;
2690 break;
2691 }
2692
2694 break;
2695 }
2697
2698 return hr;
2699}
2700
2703{
2704 return d3d_device7_SetRenderState(iface, state, value);
2705}
2706
2709{
2710 HRESULT hr;
2711 WORD old_fpucw;
2712
2713 old_fpucw = d3d_fpu_setup();
2715 set_fpu_control_word(old_fpucw);
2716
2717 return hr;
2718}
2719
2720static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2722{
2723 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2724 for this state can be directly mapped to texture stage colorop and alphaop, but
2725 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2726 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2727 alphaarg when needed.
2728
2729 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2730
2731 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2732 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2733 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2734 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2735 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2736 in device - TRUE if the app is using TEXTUREMAPBLEND.
2737
2738 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2739 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2740 unless some broken game will be found that cares. */
2741
2743 HRESULT hr;
2744
2745 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2746
2748 {
2749 WARN("Unhandled state %#x.\n", state);
2750 return DDERR_INVALIDPARAMS;
2751 }
2752
2754
2755 switch (state)
2756 {
2758 {
2759 struct ddraw_surface *surf;
2760
2761 if (value == 0)
2762 {
2763 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2764 break;
2765 }
2766
2767 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2768 if (!surf)
2769 {
2770 WARN("Invalid texture handle.\n");
2772 break;
2773 }
2774
2776 break;
2777 }
2778
2780 {
2781 device->legacyTextureBlending = TRUE;
2782
2783 switch (value)
2784 {
2785 case D3DTBLEND_MODULATE:
2786 {
2787 struct wined3d_texture *tex = NULL;
2788 BOOL tex_alpha = FALSE;
2789 DDPIXELFORMAT ddfmt;
2790
2791 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2792 {
2794
2796 ddfmt.dwSize = sizeof(ddfmt);
2797 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2798 if (ddfmt.u5.dwRGBAlphaBitMask)
2799 tex_alpha = TRUE;
2800 }
2801
2802 if (tex_alpha)
2805 else
2818 break;
2819 }
2820
2821 case D3DTBLEND_ADD:
2832 break;
2833
2847 break;
2848
2849 case D3DTBLEND_COPY:
2850 case D3DTBLEND_DECAL:
2859 break;
2860
2872 break;
2873
2874 default:
2875 FIXME("Unhandled texture environment %#x.\n", value);
2876 }
2877
2878 hr = D3D_OK;
2879 break;
2880 }
2881
2885 hr = D3D_OK;
2886 break;
2887
2888 default:
2889 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2890 break;
2891 }
2893
2894 return hr;
2895}
2896
2897static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2899{
2901
2902 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2903
2904 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2905}
2906
2907/*****************************************************************************
2908 * Direct3DDevice3::SetLightState
2909 *
2910 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2911 * light states are forwarded to Direct3DDevice7 render states
2912 *
2913 * Version 2 and 3
2914 *
2915 * Params:
2916 * LightStateType: The light state to change
2917 * Value: The value to assign to that light state
2918 *
2919 * Returns:
2920 * D3D_OK on success
2921 * DDERR_INVALIDPARAMS if the parameters were incorrect
2922 * Also check IDirect3DDevice7::SetRenderState
2923 *
2924 *****************************************************************************/
2925static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2927{
2929 HRESULT hr;
2930
2931 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2932
2934 {
2935 TRACE("Unexpected Light State Type\n");
2936 return DDERR_INVALIDPARAMS;
2937 }
2938
2941 {
2942 if (value)
2943 {
2944 struct d3d_material *m;
2945
2946 if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL)))
2947 {
2948 WARN("Invalid material handle.\n");
2950 return DDERR_INVALIDPARAMS;
2951 }
2952
2954 }
2955
2956 device->material = value;
2957 }
2958 else if (state == D3DLIGHTSTATE_COLORMODEL)
2959 {
2960 switch (value)
2961 {
2962 case D3DCOLOR_MONO:
2963 ERR("DDCOLOR_MONO should not happen!\n");
2964 break;
2965 case D3DCOLOR_RGB:
2966 /* We are already in this mode */
2967 TRACE("Setting color model to RGB (no-op).\n");
2968 break;
2969 default:
2970 ERR("Unknown color model!\n");
2972 return DDERR_INVALIDPARAMS;
2973 }
2974 }
2975 else
2976 {
2978 switch (state)
2979 {
2980 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2982 break;
2983 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2985 break;
2986 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2988 break;
2989 case D3DLIGHTSTATE_FOGEND: /* 6 */
2991 break;
2992 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2994 break;
2995 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2997 break;
2998 default:
2999 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3001 return DDERR_INVALIDPARAMS;
3002 }
3003
3004 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3006 return hr;
3007 }
3009
3010 return D3D_OK;
3011}
3012
3013static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
3015{
3017
3018 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
3019
3020 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
3021}
3022
3023/*****************************************************************************
3024 * IDirect3DDevice3::GetLightState
3025 *
3026 * Returns the current setting of a light state. The state is read from
3027 * the Direct3DDevice7 render state.
3028 *
3029 * Version 2 and 3
3030 *
3031 * Params:
3032 * LightStateType: The light state to return
3033 * Value: The address to store the light state setting at
3034 *
3035 * Returns:
3036 * D3D_OK on success
3037 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3038 * Also see IDirect3DDevice7::GetRenderState
3039 *
3040 *****************************************************************************/
3041static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
3043{
3045 HRESULT hr;
3046
3047 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3048
3050 {
3051 TRACE("Unexpected Light State Type\n");
3052 return DDERR_INVALIDPARAMS;
3053 }
3054
3055 if (!value)
3056 return DDERR_INVALIDPARAMS;
3057
3060 {
3061 *value = device->material;
3062 }
3063 else if (state == D3DLIGHTSTATE_COLORMODEL)
3064 {
3066 }
3067 else
3068 {
3070 switch (state)
3071 {
3072 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3074 break;
3075 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3077 break;
3078 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3080 break;
3081 case D3DLIGHTSTATE_FOGEND: /* 6 */
3083 break;
3084 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3086 break;
3087 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3089 break;
3090 default:
3091 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3093 return DDERR_INVALIDPARAMS;
3094 }
3095
3096 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3098 return hr;
3099 }
3101
3102 return D3D_OK;
3103}
3104
3105static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3107{
3109
3110 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3111
3112 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3113}
3114
3115/*****************************************************************************
3116 * IDirect3DDevice7::SetTransform
3117 *
3118 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3119 * in include/d3dtypes.h.
3120 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3121 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3122 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3123 *
3124 * Version 2, 3 and 7
3125 *
3126 * Params:
3127 * TransformStateType: transform state to set
3128 * Matrix: Matrix to assign to the state
3129 *
3130 * Returns:
3131 * D3D_OK on success
3132 * DDERR_INVALIDPARAMS if Matrix == NULL
3133 *
3134 *****************************************************************************/
3135static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3137{
3140
3141 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3142
3143 switch (state)
3144 {
3147 break;
3150 break;
3153 break;
3156 break;
3157 default:
3159 }
3160
3161 if (!matrix)
3162 return DDERR_INVALIDPARAMS;
3163
3164 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3168
3169 return D3D_OK;
3170}
3171
3172static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3174{
3175 return d3d_device7_SetTransform(iface, state, matrix);
3176}
3177
3180{
3181 HRESULT hr;
3182 WORD old_fpucw;
3183
3184 old_fpucw = d3d_fpu_setup();
3186 set_fpu_control_word(old_fpucw);
3187
3188 return hr;
3189}
3190
3191static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3193{
3195
3196 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3197
3198 if (!matrix)
3199 return DDERR_INVALIDPARAMS;
3200
3202 {
3203 D3DMATRIX projection;
3204
3206 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3207 wined3d_device_set_transform(device->wined3d_device,
3208 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3209 device->legacy_projection = *matrix;
3211
3212 return D3D_OK;
3213 }
3214
3215 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3216}
3217
3218static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3220{
3222
3223 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3224
3225 return IDirect3DDevice3_SetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3226}
3227
3228/*****************************************************************************
3229 * IDirect3DDevice7::GetTransform
3230 *
3231 * Returns the matrix assigned to a transform state
3232 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3233 * SetTransform
3234 *
3235 * Params:
3236 * TransformStateType: State to read the matrix from
3237 * Matrix: Address to store the matrix at
3238 *
3239 * Returns:
3240 * D3D_OK on success
3241 * DDERR_INVALIDPARAMS if Matrix == NULL
3242 *
3243 *****************************************************************************/
3244static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3246{
3249
3250 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3251
3252 switch (state)
3253 {
3256 break;
3259 break;
3262 break;
3265 break;
3266 default:
3268 }
3269
3270 if (!matrix)
3271 return DDERR_INVALIDPARAMS;
3272
3273 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3277
3278 return D3D_OK;
3279}
3280
3281static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3283{
3284 return d3d_device7_GetTransform(iface, state, matrix);
3285}
3286
3289{
3290 HRESULT hr;
3291 WORD old_fpucw;
3292
3293 old_fpucw = d3d_fpu_setup();
3295 set_fpu_control_word(old_fpucw);
3296
3297 return hr;
3298}
3299
3300static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3302{
3304
3305 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3306
3307 if (!matrix)
3308 return DDERR_INVALIDPARAMS;
3309
3311 {
3313 *matrix = device->legacy_projection;
3315 return DD_OK;
3316 }
3317
3318 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3319}
3320
3321static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3323{
3325
3326 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3327
3328 return IDirect3DDevice3_GetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3329}
3330
3331/*****************************************************************************
3332 * IDirect3DDevice7::MultiplyTransform
3333 *
3334 * Multiplies the already-set transform matrix of a transform state
3335 * with another matrix. For the world matrix, see SetTransform
3336 *
3337 * Version 2, 3 and 7
3338 *
3339 * Params:
3340 * TransformStateType: Transform state to multiply
3341 * D3DMatrix Matrix to multiply with.
3342 *
3343 * Returns
3344 * D3D_OK on success
3345 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3346 *
3347 *****************************************************************************/
3348static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3350{
3353
3354 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3355
3356 switch (state)
3357 {
3360 break;
3363 break;
3366 break;
3369 break;
3370 default:
3372 }
3373
3374 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3379
3380 return D3D_OK;
3381}
3382
3385{
3387}
3388
3391{
3392 HRESULT hr;
3393 WORD old_fpucw;
3394
3395 old_fpucw = d3d_fpu_setup();
3397 set_fpu_control_word(old_fpucw);
3398
3399 return hr;
3400}
3401
3402static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3404{
3406
3407 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3408
3410 {
3411 D3DMATRIX projection, tmp;
3412
3414 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3415 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3416 wined3d_device_set_transform(device->wined3d_device,
3417 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3418 device->legacy_projection = tmp;
3420
3421 return D3D_OK;
3422 }
3423
3424 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3425}
3426
3427static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3429{
3431
3432 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3433
3434 return IDirect3DDevice3_MultiplyTransform(&device->IDirect3DDevice3_iface, state, matrix);
3435}
3436
3437/*****************************************************************************
3438 * IDirect3DDevice7::DrawPrimitive
3439 *
3440 * Draws primitives based on vertices in an application-provided pointer
3441 *
3442 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3443 * an FVF format for D3D7
3444 *
3445 * Params:
3446 * PrimitiveType: The type of the primitives to draw
3447 * Vertex type: Flexible vertex format vertex description
3448 * Vertices: Pointer to the vertex array
3449 * VertexCount: The number of vertices to draw
3450 * Flags: As usual a few flags
3451 *
3452 * Returns:
3453 * D3D_OK on success
3454 * DDERR_INVALIDPARAMS if Vertices is NULL
3455 *
3456 *****************************************************************************/
3457
3458/* The caller is responsible for wined3d locking */
3460{
3461 HRESULT hr;
3462
3463 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3464 {
3465 UINT size = max(device->vertex_buffer_size * 2, min_size);
3467 struct wined3d_buffer *buffer;
3468
3469 TRACE("Growing vertex buffer to %u bytes\n", size);
3470
3471 desc.byte_width = size;
3473 desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
3475 desc.misc_flags = 0;
3476 desc.structure_byte_stride = 0;
3477
3478 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
3480 {
3481 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
3482 return hr;
3483 }
3484
3485 if (device->vertex_buffer)
3486 wined3d_buffer_decref(device->vertex_buffer);
3487
3488 device->vertex_buffer = buffer;
3489 device->vertex_buffer_size = size;
3490 device->vertex_buffer_pos = 0;
3491 }
3492 return D3D_OK;
3493}
3494
3495static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3496 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3498{
3501 struct wined3d_box wined3d_box = {0};
3502 UINT stride, vb_pos, size, align;
3503 struct wined3d_resource *vb;
3504 HRESULT hr;
3505
3506 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3507 iface, primitive_type, fvf, vertices, vertex_count, flags);
3508
3509 if (!vertex_count)
3510 {
3511 WARN("0 vertex count.\n");
3512 return D3D_OK;
3513 }
3514
3515 /* Get the stride */
3518
3521 if (FAILED(hr))
3522 goto done;
3523
3524 vb_pos = device->vertex_buffer_pos;
3525 align = vb_pos % stride;
3526 if (align) align = stride - align;
3527 if (vb_pos + size + align > device->vertex_buffer_size)
3528 vb_pos = 0;
3529 else
3530 vb_pos += align;
3531
3532 wined3d_box.left = vb_pos;
3533 wined3d_box.right = vb_pos + size;
3534 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3537 goto done;
3538 memcpy(wined3d_map_desc.data, vertices, size);
3540 device->vertex_buffer_pos = vb_pos + size;
3541
3542 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3543 if (FAILED(hr))
3544 goto done;
3545
3547 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
3548 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3549
3550done:
3552 return hr;
3553}
3554
3556 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3558{
3559 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3560}
3561
3563 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3565{
3566 HRESULT hr;
3567 WORD old_fpucw;
3568
3569 old_fpucw = d3d_fpu_setup();
3570 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3571 set_fpu_control_word(old_fpucw);
3572
3573 return hr;
3574}
3575
3576static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3577{
3578 BOOL enable = TRUE;
3579
3580 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3581 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
3582 enable = FALSE;
3583
3585}
3586
3587
3588static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3589 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3590 DWORD flags)
3591{
3593
3594 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3595 iface, primitive_type, fvf, vertices, vertex_count, flags);
3596
3598
3599 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3600 primitive_type, fvf, vertices, vertex_count, flags);
3601}
3602
3603static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3606{
3608 DWORD fvf;
3609
3610 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3611 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3612
3613 switch (vertex_type)
3614 {
3615 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3616 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3617 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3618 default:
3619 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3620 return DDERR_INVALIDPARAMS; /* Should never happen */
3621 }
3622
3623 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3624 primitive_type, fvf, vertices, vertex_count, flags);
3625}
3626
3627/*****************************************************************************
3628 * IDirect3DDevice7::DrawIndexedPrimitive
3629 *
3630 * Draws vertices from an application-provided pointer, based on the index
3631 * numbers in a WORD array.
3632 *
3633 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3634 * an FVF format for D3D7
3635 *
3636 * Params:
3637 * PrimitiveType: The primitive type to draw
3638 * VertexType: The FVF vertex description
3639 * Vertices: Pointer to the vertex array
3640 * VertexCount: ?
3641 * Indices: Pointer to the index array
3642 * IndexCount: Number of indices = Number of vertices to draw
3643 * Flags: As usual, some flags
3644 *
3645 * Returns:
3646 * D3D_OK on success
3647 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3648 *
3649 *****************************************************************************/
3650/* The caller is responsible for wined3d locking */
3652{
3653 HRESULT hr;
3654
3655 if (device->index_buffer_size < min_size || !device->index_buffer)
3656 {
3657 UINT size = max(device->index_buffer_size * 2, min_size);
3659 struct wined3d_buffer *buffer;
3660
3661 TRACE("Growing index buffer to %u bytes\n", size);
3662
3663 desc.byte_width = size;
3665 desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
3667 desc.misc_flags = 0;
3668 desc.structure_byte_stride = 0;
3669
3670 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
3672 {
3673 ERR("Failed to create index buffer, hr %#x.\n", hr);
3674 return hr;
3675 }
3676
3677 if (device->index_buffer)
3678 wined3d_buffer_decref(device->index_buffer);
3679 device->index_buffer = buffer;
3680 device->index_buffer_size = size;
3681 device->index_buffer_pos = 0;
3682 }
3683 return D3D_OK;
3684}
3685
3686static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3687 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3688 WORD *indices, DWORD index_count, DWORD flags)
3689{
3691 HRESULT hr;
3693 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3695 struct wined3d_box wined3d_box = {0};
3696 struct wined3d_resource *ib, *vb;
3697 UINT vb_pos, ib_pos, align;
3698
3699 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3700 "indices %p, index_count %u, flags %#x.\n",
3701 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3702
3703 if (!vertex_count || !index_count)
3704 {
3705 WARN("0 vertex or index count.\n");
3706 return D3D_OK;
3707 }
3708
3709 /* Set the D3DDevice's FVF */
3711
3713 if (FAILED(hr))
3714 goto done;
3715
3716 vb_pos = device->vertex_buffer_pos;
3717 align = vb_pos % stride;
3718 if (align) align = stride - align;
3719 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3720 vb_pos = 0;
3721 else
3722 vb_pos += align;
3723
3724 wined3d_box.left = vb_pos;
3725 wined3d_box.right = vb_pos + vtx_size;
3726 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3729 goto done;
3730 memcpy(wined3d_map_desc.data, vertices, vtx_size);
3732 device->vertex_buffer_pos = vb_pos + vtx_size;
3733
3735 if (FAILED(hr))
3736 goto done;
3737 ib_pos = device->index_buffer_pos;
3738 if (device->index_buffer_size - idx_size < ib_pos)
3739 ib_pos = 0;
3740
3741 wined3d_box.left = ib_pos;
3742 wined3d_box.right = ib_pos + idx_size;
3743 ib = wined3d_buffer_get_resource(device->index_buffer);
3746 goto done;
3747 memcpy(wined3d_map_desc.data, indices, idx_size);
3749 device->index_buffer_pos = ib_pos + idx_size;
3750
3751 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3752 if (FAILED(hr))
3753 goto done;
3754 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
3755
3757 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
3758 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3759 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3760
3761done:
3763 return hr;
3764}
3765
3767 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3768 WORD *indices, DWORD index_count, DWORD flags)
3769{
3770 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3771 vertices, vertex_count, indices, index_count, flags);
3772}
3773
3775 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3776 WORD *indices, DWORD index_count, DWORD flags)
3777{
3778 HRESULT hr;
3779 WORD old_fpucw;
3780
3781 old_fpucw = d3d_fpu_setup();
3782 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3783 vertices, vertex_count, indices, index_count, flags);
3784 set_fpu_control_word(old_fpucw);
3785
3786 return hr;
3787}
3788
3789static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3790 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3791 WORD *indices, DWORD index_count, DWORD flags)
3792{
3794
3795 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3796 "indices %p, index_count %u, flags %#x.\n",
3797 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3798
3800
3801 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3802 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3803}
3804
3805static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3807 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3808{
3810 DWORD fvf;
3811
3812 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3813 "indices %p, index_count %u, flags %#x.\n",
3814 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3815
3816 switch (vertex_type)
3817 {
3818 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3819 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3820 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3821 default:
3822 ERR("Unhandled vertex type %#x.\n", vertex_type);
3823 return DDERR_INVALIDPARAMS; /* Should never happen */
3824 }
3825
3826 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3827 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3828}
3829
3830/*****************************************************************************
3831 * IDirect3DDevice3::End
3832 *
3833 * Ends a draw begun with IDirect3DDevice3::Begin or
3834 * IDirect3DDevice::BeginIndexed. The vertices specified with
3835 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3836 * the IDirect3DDevice3::DrawPrimitive method. So far only
3837 * non-indexed mode is supported
3838 *
3839 * Version 2 and 3
3840 *
3841 * Params:
3842 * Flags: Some flags, as usual. Don't know which are defined
3843 *
3844 * Returns:
3845 * The return value of IDirect3DDevice3::DrawPrimitive
3846 *
3847 *****************************************************************************/
3848static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3849{
3851
3852 TRACE("iface %p, flags %#x.\n", iface, flags);
3853
3854 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3855 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3856}
3857
3858static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3859{
3861
3862 TRACE("iface %p, flags %#x.\n", iface, flags);
3863
3864 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3865}
3866
3867/*****************************************************************************
3868 * IDirect3DDevice7::SetClipStatus
3869 *
3870 * Sets the clip status. This defines things as clipping conditions and
3871 * the extents of the clipping region.
3872 *
3873 * Version 2, 3 and 7
3874 *
3875 * Params:
3876 * ClipStatus:
3877 *
3878 * Returns:
3879 * D3D_OK because it's a stub
3880 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3881 *
3882 *****************************************************************************/
3883static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3884{
3885 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3886
3887 return D3D_OK;
3888}
3889
3890static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3891{
3893
3894 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3895
3896 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3897}
3898
3899static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3900{
3902
3903 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3904
3905 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3906}
3907
3908/*****************************************************************************
3909 * IDirect3DDevice7::GetClipStatus
3910 *
3911 * Returns the clip status
3912 *
3913 * Params:
3914 * ClipStatus: Address to write the clip status to
3915 *
3916 * Returns:
3917 * D3D_OK because it's a stub
3918 *
3919 *****************************************************************************/
3920static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3921{
3922 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3923
3924 return D3D_OK;
3925}
3926
3927static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3928{
3930
3931 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3932
3933 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3934}
3935
3936static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3937{
3939
3940 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3941
3942 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3943}
3944
3945/*****************************************************************************
3946 * IDirect3DDevice::DrawPrimitiveStrided
3947 *
3948 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3949 *
3950 * Version 3 and 7
3951 *
3952 * Params:
3953 * PrimitiveType: The primitive type to draw
3954 * VertexType: The FVF description of the vertices to draw (for the stride??)
3955 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3956 * the vertex data locations
3957 * VertexCount: The number of vertices to draw
3958 * Flags: Some flags
3959 *
3960 * Returns:
3961 * D3D_OK, because it's a stub
3962 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3963 *
3964 *****************************************************************************/
3966{
3967 DWORD i, tex, offset;
3968
3969 for (i = 0; i < count; i++)
3970 {
3971 /* The contents of the strided data are determined by the fvf,
3972 * not by the members set in src. So it's valid
3973 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3974 * not set in the fvf. */
3975 if (fvf & D3DFVF_POSITION_MASK)
3976 {
3977 offset = i * src->position.dwStride;
3978 if (fvf & D3DFVF_XYZRHW)
3979 {
3980 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3981 dst += 4 * sizeof(float);
3982 }
3983 else
3984 {
3985 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3986 dst += 3 * sizeof(float);
3987 }
3988 }
3989
3990 if (fvf & D3DFVF_NORMAL)
3991 {
3992 offset = i * src->normal.dwStride;
3993 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3994 dst += 3 * sizeof(float);
3995 }
3996
3997 if (fvf & D3DFVF_DIFFUSE)
3998 {
3999 offset = i * src->diffuse.dwStride;
4000 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
4001 dst += sizeof(DWORD);
4002 }
4003
4004 if (fvf & D3DFVF_SPECULAR)
4005 {
4006 offset = i * src->specular.dwStride;
4007 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
4008 dst += sizeof(DWORD);
4009 }
4010
4011 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
4012 {
4013 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
4014 offset = i * src->textureCoords[tex].dwStride;
4015 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
4016 dst += attrib_count * sizeof(float);
4017 }
4018 }
4019}
4020
4023{
4025 HRESULT hr;
4026 UINT dst_stride = get_flexible_vertex_size(fvf);
4027 UINT dst_size = dst_stride * vertex_count;
4029 struct wined3d_box wined3d_box = {0};
4030 struct wined3d_resource *vb;
4031 UINT vb_pos, align;
4032
4033 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4034 iface, primitive_type, fvf, strided_data, vertex_count, flags);
4035
4036 if (!vertex_count)
4037 {
4038 WARN("0 vertex count.\n");
4039 return D3D_OK;
4040 }
4041
4044 if (FAILED(hr))
4045 goto done;
4046
4047 vb_pos = device->vertex_buffer_pos;
4048 align = vb_pos % dst_stride;
4049 if (align) align = dst_stride - align;
4050 if (vb_pos + dst_size + align > device->vertex_buffer_size)
4051 vb_pos = 0;
4052 else
4053 vb_pos += align;
4054
4055 wined3d_box.left = vb_pos;
4056 wined3d_box.right = vb_pos + dst_size;
4057 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4060 goto done;
4063 device->vertex_buffer_pos = vb_pos + dst_size;
4064
4065 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride);
4066 if (FAILED(hr))
4067 goto done;
4069
4070 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4071 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, vertex_count);
4072
4073done:
4075 return hr;
4076}
4077
4079 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4080 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4081{
4082 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4083 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4084}
4085
4087 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4088 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4089{
4090 HRESULT hr;
4091 WORD old_fpucw;
4092
4093 old_fpucw = d3d_fpu_setup();
4094 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4095 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4096 set_fpu_control_word(old_fpucw);
4097
4098 return hr;
4099}
4100
4101static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4102 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4103 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4104{
4106
4107 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4108 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4109
4110 setup_lighting(device, VertexType, Flags);
4111
4112 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
4113 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4114}
4115
4116/*****************************************************************************
4117 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4118 *
4119 * Draws primitives specified by strided data locations based on indices
4120 *
4121 * Version 3 and 7
4122 *
4123 * Params:
4124 * PrimitiveType:
4125 *
4126 * Returns:
4127 * D3D_OK, because it's a stub
4128 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4129 * (DDERR_INVALIDPARAMS if Indices is NULL)
4130 *
4131 *****************************************************************************/
4134 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4135{
4137 UINT vtx_dst_stride = get_flexible_vertex_size(fvf);
4138 UINT vtx_dst_size = vertex_count * vtx_dst_stride;
4139 UINT idx_size = index_count * sizeof(WORD);
4141 struct wined3d_box wined3d_box = {0};
4142 struct wined3d_resource *ib, *vb;
4143 UINT vb_pos, align;
4144 UINT ib_pos;
4145 HRESULT hr;
4146
4147 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, "
4148 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4149 iface, primitive_type, fvf, strided_data, vertex_count, indices, index_count, flags);
4150
4151 if (!vertex_count || !index_count)
4152 {
4153 WARN("0 vertex or index count.\n");
4154 return D3D_OK;
4155 }
4156
4158
4160 if (FAILED(hr))
4161 goto done;
4162
4163 vb_pos = device->vertex_buffer_pos;
4164 align = vb_pos % vtx_dst_stride;
4165 if (align) align = vtx_dst_stride - align;
4166 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4167 vb_pos = 0;
4168 else
4169 vb_pos += align;
4170
4171 wined3d_box.left = vb_pos;
4172 wined3d_box.right = vb_pos + vtx_dst_size;
4173 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4176 goto done;
4179 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4180
4182 if (FAILED(hr))
4183 goto done;
4184 ib_pos = device->index_buffer_pos;
4185 if (device->index_buffer_size - idx_size < ib_pos)
4186 ib_pos = 0;
4187
4188 wined3d_box.left = ib_pos;
4189 wined3d_box.right = ib_pos + idx_size;
4190 ib = wined3d_buffer_get_resource(device->index_buffer);
4193 goto done;
4194 memcpy(wined3d_map_desc.data, indices, idx_size);
4196 device->index_buffer_pos = ib_pos + idx_size;
4197
4198 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride);
4199 if (FAILED(hr))
4200 goto done;
4201 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4202 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride);
4203
4205 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4206 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4207
4208done:
4210 return hr;
4211}
4212
4214 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4215 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4216 WORD *Indices, DWORD IndexCount, DWORD Flags)
4217{
4218 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4219 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4220}
4221
4223 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4224 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4225 WORD *Indices, DWORD IndexCount, DWORD Flags)
4226{
4227 HRESULT hr;
4228 WORD old_fpucw;
4229
4230 old_fpucw = d3d_fpu_setup();
4231 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4232 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4233 set_fpu_control_word(old_fpucw);
4234
4235 return hr;
4236}
4237
4239 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4240 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4241 DWORD IndexCount, DWORD Flags)
4242{
4244
4245 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4246 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4247
4248 setup_lighting(device, VertexType, Flags);
4249
4250 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4251 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4252}
4253
4254/*****************************************************************************
4255 * IDirect3DDevice7::DrawPrimitiveVB
4256 *
4257 * Draws primitives from a vertex buffer to the screen.
4258 *
4259 * Version 3 and 7
4260 *
4261 * Params:
4262 * PrimitiveType: Type of primitive to be rendered.
4263 * D3DVertexBuf: Source Vertex Buffer
4264 * StartVertex: Index of the first vertex from the buffer to be rendered
4265 * NumVertices: Number of vertices to be rendered
4266 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4267 *
4268 * Return values
4269 * D3D_OK on success
4270 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4271 *
4272 *****************************************************************************/
4274 IDirect3DVertexBuffer7 *vb, DWORD start_vertex, DWORD vertex_count, DWORD flags)
4275{
4278 HRESULT hr;
4279 DWORD stride;
4280
4281 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4282 iface, primitive_type, vb, start_vertex, vertex_count, flags);
4283
4284 if (!vertex_count)
4285 {
4286 WARN("0 vertex count.\n");
4287 return D3D_OK;
4288 }
4289
4291
4294 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
4295 0, vb_impl->wined3d_buffer, 0, stride)))
4296 {
4297 WARN("Failed to set stream source, hr %#x.\n", hr);
4299 return hr;
4300 }
4301
4302 /* Now draw the primitives */
4303 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4304 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count);
4305
4307
4308 return hr;
4309}
4310