ReactOS  0.4.13-dev-443-g10f00f8
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 
46 static inline void set_fpu_control_word(WORD fpucw)
47 {
48 #if defined(__i386__) && defined(__GNUC__)
49  __asm__ volatile ("fldcw %0" : : "m" (fpucw));
50 #elif defined(__i386__) && defined(_MSC_VER)
51  __asm fldcw fpucw;
52 #endif
53 }
54 
55 static inline WORD d3d_fpu_setup(void)
56 {
57  WORD oldcw;
58 
59 #if defined(__i386__) && defined(__GNUC__)
60  __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
61 #elif defined(__i386__) && defined(_MSC_VER)
62  __asm fnstcw oldcw;
63 #else
64  static BOOL warned = FALSE;
65  if(!warned)
66  {
67  FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
68  warned = TRUE;
69  }
70  return 0;
71 #endif
72 
73  set_fpu_control_word(0x37f);
74 
75  return oldcw;
76 }
77 
78 static inline struct d3d_device *impl_from_IUnknown(IUnknown *iface)
79 {
80  return CONTAINING_RECORD(iface, struct d3d_device, IUnknown_inner);
81 }
82 
84 {
85  struct d3d_device *device = impl_from_IUnknown(iface);
86 
87  TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
88 
89  if (!riid)
90  {
91  *out = NULL;
92  return DDERR_INVALIDPARAMS;
93  }
94 
96  {
97  IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
98  *out = &device->IDirect3DDevice7_iface;
99  return S_OK;
100  }
101 
102  if (device->version == 7)
103  {
104  if (IsEqualGUID(&IID_IDirect3DDevice7, riid))
105  {
106  IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
107  *out = &device->IDirect3DDevice7_iface;
108  return S_OK;
109  }
110  }
111  else
112  {
113  if (IsEqualGUID(&IID_IDirect3DDevice3, riid) && device->version == 3)
114  {
115  IDirect3DDevice3_AddRef(&device->IDirect3DDevice3_iface);
116  *out = &device->IDirect3DDevice3_iface;
117  return S_OK;
118  }
119 
120  if (IsEqualGUID(&IID_IDirect3DDevice2, riid) && device->version >= 2)
121  {
122  IDirect3DDevice2_AddRef(&device->IDirect3DDevice2_iface);
123  *out = &device->IDirect3DDevice2_iface;
124  return S_OK;
125  }
126 
127  if (IsEqualGUID(&IID_IDirect3DDevice, riid))
128  {
129  IDirect3DDevice_AddRef(&device->IDirect3DDevice_iface);
130  *out = &device->IDirect3DDevice_iface;
131  return S_OK;
132  }
133  }
134 
135  WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
136 
137  *out = NULL;
138  return E_NOINTERFACE;
139 }
140 
141 static HRESULT WINAPI d3d_device7_QueryInterface(IDirect3DDevice7 *iface, REFIID riid, void **out)
142 {
144 
145  TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
146 
147  return IUnknown_QueryInterface(device->outer_unknown, riid, out);
148 }
149 
150 static HRESULT WINAPI d3d_device3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid, void **out)
151 {
153 
154  TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
155 
156  return IUnknown_QueryInterface(device->outer_unknown, riid, out);
157 }
158 
159 static HRESULT WINAPI d3d_device2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid, void **out)
160 {
162 
163  TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
164 
165  return IUnknown_QueryInterface(device->outer_unknown, riid, out);
166 }
167 
168 static HRESULT WINAPI d3d_device1_QueryInterface(IDirect3DDevice *iface, REFIID riid, void **out)
169 {
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 
187 static 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 
196 static 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 
205 static 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 
214 static 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 
249  wined3d_device_set_rendertarget_view(This->wined3d_device, 0, NULL, FALSE);
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  {
263  case DDRAW_HANDLE_FREE:
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 
274  case DDRAW_HANDLE_MATRIX:
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 */
325  heap_free(This);
327  }
328 
329  TRACE("Done\n");
330  return ref;
331 }
332 
333 static 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 
342 static 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 
351 static 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 
360 static 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  *****************************************************************************/
387 static 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 
398 static 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 
469 static 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 
509 static 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 
519 static 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  *****************************************************************************/
541 static 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 
565 static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface,
566  IDirect3DTexture *tex1, IDirect3DTexture *tex2)
567 {
569  struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(tex1);
570  struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(tex2);
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  *****************************************************************************/
597 static 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 
614 static 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 
623 static 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  *****************************************************************************/
652 static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface,
653  D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown)
654 {
656  struct d3d_execute_buffer *object;
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)
663  return CLASS_E_NOAGGREGATION;
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  *****************************************************************************/
702 static 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  *****************************************************************************/
740 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
741 {
743  struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
744 
745  TRACE("iface %p, viewport %p.\n", iface, viewport);
746 
747  /* Sanity check */
748  if(!vp)
749  return DDERR_INVALIDPARAMS;
750 
752  IDirect3DViewport3_AddRef(viewport);
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 
761 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
762  IDirect3DViewport2 *viewport)
763 {
765  struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
766 
767  TRACE("iface %p, viewport %p.\n", iface, viewport);
768 
769  return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
770 }
771 
772 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
773 {
775  struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
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  *****************************************************************************/
798 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
799 {
801  struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
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");
823  IDirect3DViewport3_Release(viewport);
824  device->current_viewport = NULL;
825  }
826 
827  vp->active_device = NULL;
828  list_remove(&vp->entry);
829 
830  IDirect3DViewport3_Release(viewport);
831 
833 
834  return D3D_OK;
835 }
836 
837 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
838 {
840  struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
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 
848 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
849 {
851  struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
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  *****************************************************************************/
877 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
878  IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
879 {
880  struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
881  struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
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  {
919  next = LIST_ENTRY(entry, struct d3d_viewport, entry);
920  *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
921  }
922  else
923  *lplpDirect3DViewport3 = NULL;
924 
926 
927  return D3D_OK;
928 }
929 
930 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
931  IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
932 {
934  struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
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 
947 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
948  IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
949 {
951  struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
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  *****************************************************************************/
985 static 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  *****************************************************************************/
1010 static 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  *****************************************************************************/
1036 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1038 {
1039  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1040  struct wined3d_display_mode mode;
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 
1158 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1160 {
1161  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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  *****************************************************************************/
1178 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1180 {
1181  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1182  struct wined3d_display_mode mode;
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 
1247 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1249 {
1250  struct d3d_device *device = impl_from_IDirect3DDevice(iface);
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  *****************************************************************************/
1273 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1274 {
1275  struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1276  D3DMATRIX *matrix;
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");
1296  heap_free(matrix);
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  *****************************************************************************/
1328 static 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  *****************************************************************************/
1386 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1387  D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1388 {
1389  struct d3d_device *device = impl_from_IDirect3DDevice(iface);
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  *****************************************************************************/
1428 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1429 {
1430  struct d3d_device *device = impl_from_IDirect3DDevice(iface);
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  *****************************************************************************/
1466 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1467 {
1468  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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 
1481 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1482 {
1483  return d3d_device7_BeginScene(iface);
1484 }
1485 
1486 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
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 
1498 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1499 {
1500  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1501 
1502  TRACE("iface %p.\n", iface);
1503 
1504  return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1505 }
1506 
1507 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1508 {
1509  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1510 
1511  TRACE("iface %p.\n", iface);
1512 
1513  return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1514 }
1515 
1516 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1517 {
1518  struct d3d_device *device = impl_from_IDirect3DDevice(iface);
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  *****************************************************************************/
1539 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1540 {
1541  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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 
1571 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1572 {
1573  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1574 
1575  TRACE("iface %p.\n", iface);
1576 
1577  return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1578 }
1579 
1580 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1581 {
1582  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1583 
1584  TRACE("iface %p.\n", iface);
1585 
1586  return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1587 }
1588 
1590 {
1591  struct d3d_device *device = impl_from_IDirect3DDevice(iface);
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  *****************************************************************************/
1612 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1613 {
1614  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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 
1628 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1629 {
1630  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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 
1644 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1645 {
1646  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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 
1660 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1661 {
1662  struct d3d_device *device = impl_from_IDirect3DDevice(iface);
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  *****************************************************************************/
1692 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1693 {
1694  struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
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 
1740 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1741 {
1742  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1743  struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
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  *****************************************************************************/
1766 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1767 {
1768  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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");
1777  return D3DERR_NOCURRENTVIEWPORT;
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 
1788 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1789 {
1790  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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 
1820  if (FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device,
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 
1832 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1834 {
1836  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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;
1871  return DDERR_INVALIDPIXELFORMAT;
1872  }
1873 
1876  return hr;
1877 }
1878 
1879 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
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 
1898 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1899  IDirectDrawSurface4 *target, DWORD flags)
1900 {
1902  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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;
1930  return DDERR_INVALIDPIXELFORMAT;
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 
1948 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1949  IDirectDrawSurface *target, DWORD flags)
1950 {
1952  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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;
1979  return DDERR_INVALIDPIXELFORMAT;
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  *****************************************************************************/
2014 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
2015 {
2016  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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 
2031 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
2032 {
2033  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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 
2052 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
2053 {
2054  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
2091 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
2092  D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
2093 {
2094  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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 
2110 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2112 {
2113  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2114  DWORD fvf;
2115 
2116  TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2117  iface, primitive_type, vertex_type, flags);
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  *****************************************************************************/
2151 static 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 
2162 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2164  void *vertices, DWORD vertex_count, DWORD flags)
2165 {
2166  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
2203 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2204 {
2205  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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 
2233 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2234 {
2235  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
2255 static 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 
2262 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2263 {
2264  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
2288 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2290 {
2291  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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 
2306  tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2307  switch (tex_mag)
2308  {
2309  case WINED3D_TEXF_POINT:
2311  break;
2312  case WINED3D_TEXF_LINEAR:
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 
2327  tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2328  tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
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;
2340  case WINED3D_TEXF_LINEAR:
2342  break;
2343  default:
2344  ERR("Unhandled mip filter %#x.\n", tex_mip);
2346  break;
2347  }
2348  break;
2349  case WINED3D_TEXF_LINEAR:
2350  switch (tex_mip)
2351  {
2352  case WINED3D_TEXF_NONE:
2354  break;
2355  case WINED3D_TEXF_POINT:
2357  break;
2358  case WINED3D_TEXF_LINEAR:
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 
2394  case D3DRENDERSTATE_ZBIAS:
2396  break;
2397 
2398  default:
2401  {
2402  FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2403  hr = E_NOTIMPL;
2404  break;
2405  }
2406  *value = wined3d_device_get_render_state(device->wined3d_device, state);
2407  }
2409 
2410  return hr;
2411 }
2412 
2413 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
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 
2432 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2434 {
2435  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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 
2474  colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1);
2475  colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2);
2477  alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1);
2478  alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2);
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  {
2500  struct wined3d_resource_desc desc;
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 
2534 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2536 {
2537  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
2557 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2559 {
2560  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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:
2589  case D3DFILTER_MIPNEAREST:
2591  tex_mag = WINED3D_TEXF_POINT;
2592  break;
2593  case D3DFILTER_LINEAR:
2594  case D3DFILTER_MIPLINEAR:
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 
2604  wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
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;
2623  case D3DFILTER_MIPNEAREST:
2624  tex_min = WINED3D_TEXF_POINT;
2625  tex_mip = WINED3D_TEXF_POINT;
2626  break;
2627  case D3DFILTER_MIPLINEAR:
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 
2647  wined3d_device_set_sampler_state(device->wined3d_device,
2648  0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2649  wined3d_device_set_sampler_state(device->wined3d_device,
2650  0, WINED3D_SAMP_MIN_FILTER, tex_min);
2651  break;
2652  }
2653 
2655  wined3d_device_set_sampler_state(device->wined3d_device,
2657  /* Drop through */
2659  wined3d_device_set_sampler_state(device->wined3d_device,
2661  break;
2663  wined3d_device_set_sampler_state(device->wined3d_device,
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 
2680  case D3DRENDERSTATE_ZBIAS:
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 
2701 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
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 
2720 static 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 
2742  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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  {
2793  struct wined3d_resource_desc desc;
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 
2861  case D3DTBLEND_DECALALPHA:
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 
2897 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2899 {
2900  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
2925 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2927 {
2928  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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  {
2977  D3DRENDERSTATETYPE rs;
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 */
2990  rs = D3DRENDERSTATE_FOGEND;
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 
3013 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
3015 {
3016  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
3041 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
3043 {
3044  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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  {
3065  *value = D3DCOLOR_RGB;
3066  }
3067  else
3068  {
3069  D3DRENDERSTATETYPE rs;
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 */
3082  rs = D3DRENDERSTATE_FOGEND;
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 
3105 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3107 {
3108  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
3135 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3137 {
3138  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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:
3158  wined3d_state = state;
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 
3172 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3174 {
3175  return d3d_device7_SetTransform(iface, state, matrix);
3176 }
3177 
3178 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
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 
3191 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3193 {
3194  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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 
3218 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3220 {
3221  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
3244 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3246 {
3247  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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:
3267  wined3d_state = state;
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 
3281 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3283 {
3284  return d3d_device7_GetTransform(iface, state, matrix);
3285 }
3286 
3287 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
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 
3300 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3302 {
3303  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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 
3321 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3323 {
3324  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
3348 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3350 {
3351  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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:
3371  wined3d_state = state;
3372  }
3373 
3374  /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3376  wined3d_device_multiply_transform(device->wined3d_device,
3377  wined3d_state, (struct wined3d_matrix *)matrix);
3379 
3380  return D3D_OK;
3381 }
3382 
3385 {
3386  return d3d_device7_MultiplyTransform(iface, state, matrix);
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 
3402 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3404 {
3405  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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 
3427 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3429 {
3430  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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);
3466  struct wined3d_buffer_desc desc;
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 
3495 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3496  D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3498 {
3499  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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 */
3517  size = vertex_count * 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);
3539  wined3d_resource_unmap(vb, 0);
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 
3546  wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
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 
3550 done:
3552  return hr;
3553 }
3554 
3555 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
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 
3576 static 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 
3588 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3589  D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3590  DWORD flags)
3591 {
3592  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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 
3597  setup_lighting(device, fvf, flags);
3598 
3599  return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3600  primitive_type, fvf, vertices, vertex_count, flags);
3601 }
3602 
3603 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3606 {
3607  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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);
3658  struct wined3d_buffer_desc desc;
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 
3686 static 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 {
3690  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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);
3731  wined3d_resource_unmap(vb, 0);
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);
3748  wined3d_resource_unmap(ib, 0);
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 
3756  wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
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 
3761 done:
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 
3789 static 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 {
3793  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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 
3799  setup_lighting(device, fvf, flags);
3800 
3801  return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3802  primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3803 }
3804 
3805 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3807  DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3808 {
3809  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
3848 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3849 {
3850  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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 
3858 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3859 {
3860  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
3883 static 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 
3890 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3891 {
3892  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3893 
3894  TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3895 
3896  return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3897 }
3898 
3899 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3900 {
3901  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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  *****************************************************************************/
3920 static 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 
3927 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3928 {
3929  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3930 
3931  TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3932 
3933  return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3934 }
3935 
3936 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3937 {
3938  struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
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 {
4024  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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;
4061  pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4062  wined3d_resource_unmap(vb, 0);
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;
4068  wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
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 
4073 done:
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 
4101 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4102  D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4103  D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4104 {
4105  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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  *****************************************************************************/
4132 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4134  DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4135 {
4136  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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 
4159  hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
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;
4177  pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4178  wined3d_resource_unmap(vb, 0);
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);
4195  wined3d_resource_unmap(ib, 0);
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 
4204  wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
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 
4208 done:
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 {
4243  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
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 {
4276  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
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 
4290  stride = get_flexible_vertex_size(vb_impl->fvf);
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 
4311 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4312  IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4313 {
4314  return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4315 }
4316 
4317 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4318  IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4319 {
4320  HRESULT hr;
4321  WORD old_fpucw;
4322 
4323  old_fpucw = d3d_fpu_setup();
4324  hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4325  set_fpu_control_word(old_fpucw);
4326 
4327  return hr;
4328 }
4329 
4330 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4331  IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4332 {
4333  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4334  struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf);
4335 
4336  TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4337  iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4338 
4339  setup_lighting(device, vb->fvf, Flags);
4340 
4341  return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4342  PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4343 }
4344 
4345 /*****************************************************************************
4346  * IDirect3DDevice7::DrawIndexedPrimitiveVB
4347  *
4348  * Draws primitives from a vertex buffer to the screen
4349  *
4350  * Params:
4351  * PrimitiveType: Type of primitive to be rendered.
4352  * D3DVertexBuf: Source Vertex Buffer
4353  * StartVertex: Index of the first vertex from the buffer to be rendered
4354  * NumVertices: Number of vertices to be rendered
4355  * Indices: Array of DWORDs used to index into the Vertices
4356  * IndexCount: Number of indices in Indices
4357  * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4358  *
4359  * Return values
4360  *
4361  *****************************************************************************/
4362 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4363  D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer7 *vb,
4364  DWORD start_vertex, DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4365 {
4366  struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4370  struct wined3d_box wined3d_box = {0};
4371  struct wined3d_resource *ib;
4372  HRESULT hr;
4373  UINT ib_pos;
4374 
4375  TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, "
4376  "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4377  iface, primitive_type, vb, start_vertex, vertex_count, indices, index_count, flags);
4378 
4379  if (!vertex_count || !index_count)
4380  {
4381  WARN("0 vertex or index count.\n");
4382  return D3D_OK;
4383  }
4384 
4385  /* Steps:
4386  * 1) Upload the indices to the index buffer
4387  * 2) Set the index source
4388  * 3) Set the Vertex Buffer as the Stream source
4389  * 4) Call wined3d_device_draw_indexed_primitive()
4390  */
4391 
4393 
4395 
4396  hr = d3d_device_prepare_index_buffer(device, index_count * sizeof(WORD));
4397  if (FAILED(hr))
4398  {
4400  return hr;
4401  }
4402  ib_pos = device->index_buffer_pos;
4403 
4404  if (device->index_buffer_size - index_count * sizeof(WORD) < ib_pos)
4405  ib_pos = 0;
4406 
4407  /* Copy the index stream into the index buffer. */
4408  wined3d_box.left = ib_pos;
4409  wined3d_box.right = ib_pos + index_count * sizeof(WORD);
4410  ib = wined3d_buffer_get_resource(device->index_buffer);
4413  {
4414  ERR("Failed to map buffer, hr %#x.\n", hr);
4416  return hr;
4417  }
4418  memcpy(wined3d_map_desc.data, indices, index_count * sizeof(WORD));
4419  wined3d_resource_unmap(ib, 0);
4420  device->index_buffer_pos = ib_pos + index_count * sizeof(WORD);
4421 
4422  /* Set the index stream */
4423  wined3d_device_set_base_vertex_index(device->wined3d_device, start_vertex);
4424  wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4425 
4426  /* Set the vertex stream source */
4427  if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
4428  0, vb_impl->wined3d_buffer, 0, stride)))
4429  {
4430  ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device, hr);
4432  return hr;
4433  }
4434 
4435  wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4436  hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4437 
4439 
4440  return hr;
4441 }
4442 
4444  D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4445  DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4446 {
4447  return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4448  D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4449 }
4450 
4452  D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4453  DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4454 {
4455  HRESULT hr;
4456  WORD old_fpucw;
4457 
4458  old_fpucw = d3d_fpu_setup();
4459  hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4460  D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4461  set_fpu_control_word(old_fpucw);
4462 
4463  return hr;
4464 }
4465 
4466 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4467  D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4468  DWORD IndexCount, DWORD Flags)
4469 {
4470  struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4471  struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf);
4472 
4473  TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4474  iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4475 
4476  setup_lighting(device, vb->fvf, Flags);
4477 
4478  return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4479  &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4480 }
4481 
4482 /*****************************************************************************
4483  * IDirect3DDevice7::ComputeSphereVisibility
4484  *
4485  * Calculates the visibility of spheres in the current viewport. The spheres
4486  * are passed in the Centers and Radii arrays, the results are passed back
4487  * in the ReturnValues array. Return values are either completely visible,
4488  * partially visible or completely invisible.
4489  * The return value consists of a combination of D3DCLIP_* flags, or is
4490  * 0 if the sphere is completely visible (according to the SDK, not checked)
4491  *
4492  * Version 3 and 7
4493  *
4494  * Params:
4495  * Centers: Array containing the sphere centers
4496  * Radii: Array containing the sphere radii
4497  * NumSpheres: The number of centers and radii in the arrays
4498  * Flags: Some flags
4499  * ReturnValues: Array to write the results to
4500  *
4501  * Returns:
4502  * D3D_OK
4503  * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4504  * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4505  * is singular)
4506  *
4507  *****************************************************************************/
4508 
4509 static DWORD in_plane(UINT idx, struct wined3d_vec4 p, D3DVECTOR center, D3DVALUE radius, BOOL equality)
4510 {
4511  float distance, norm;
4512 
4513  norm = sqrtf(p.x * p.x + p.y * p.y + p.z * p.z);
4514  distance = (p.x * center.u1.x + p.y * center.u2.y + p.z * center.u3.z + p.w) / norm;
4515 
4516  if (equality)
4517  {
4518  if (fabs(distance) <= radius)
4519  return D3DSTATUS_CLIPUNIONLEFT << idx;
4520  if (distance <= -radius)
4522  }
4523  else
4524  {
4525  if (fabs(distance) < radius)
4526  return D3DSTATUS_CLIPUNIONLEFT << idx;
4527  if (distance < -radius)
4529  }
4530  return 0;
4531 }
4532 
4534 {
4535  D3DMATRIX m, temp;
4536 
4537  /* We want the wined3d matrices since those include the legacy viewport
4538  * transformation. */
4540  wined3d_device_get_transform(device->wined3d_device,
4541  WINED3D_TS_WORLD, (struct wined3d_matrix *)&m);
4542 
4543  wined3d_device_get_transform(device->wined3d_device,
4544  WINED3D_TS_VIEW, (struct wined3d_matrix *)&temp);
4545  multiply_matrix(&m, &temp, &m);
4546 
4547  wined3d_device_get_transform(device->wined3d_device,
4549  multiply_matrix(&m, &temp, &m);
4551 
4552  /* Left plane. */
4553  plane[0].x = m._14 + m._11;
4554  plane[0].y = m._24 + m._21;
4555  plane[0].z = m._34 + m._31;
4556  plane[0].w = m._44 + m._41;
4557 
4558  /* Right plane. */
4559  plane[1].x = m._14 - m._11;
4560  plane[1].y = m._24 - m._21;
4561  plane[1].z = m._34 - m._31;
4562  plane[1].w = m._44 - m._41;
4563 
4564  /* Top plane. */
4565  plane[2].x = m._14 - m._12;
4566  plane[2].y = m._24 - m._22;
4567  plane[2].z = m._34 - m._32;
4568  plane[2].w = m._44 - m._42;
4569 
4570  /* Bottom plane. */
4571  plane[3].x = m._14 + m._12;
4572  plane[3].y = m._24 + m._22;
4573  plane[3].z = m._34 + m._32;
4574  plane[3].w = m._44 + m._42;
4575 
4576  /* Front plane. */
4577  plane[4].x = m._13;
4578  plane[4].y = m._23;
4579  plane[4].z = m._33;
4580  plane[4].w = m._43;
4581 
4582  /* Back plane. */
4583  plane[5].x = m._14 - m._13;
4584  plane[5].y =