ReactOS  0.4.14-dev-606-g14ebc0b
ddraw.c
Go to the documentation of this file.
1 /*
2  * Copyright 1997-2000 Marcus Meissner
3  * Copyright 1998-2000 Lionel Ulmer
4  * Copyright 2000-2001 TransGaming Technologies Inc.
5  * Copyright 2006 Stefan Dösinger
6  * Copyright 2008 Denver Gingerich
7  * Copyright 2007-2008, 2011, 2013 Stefan Dösinger for CodeWeavers
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include "config.h"
25 #include "wine/port.h"
26 
27 #include "ddraw_private.h"
28 
29 #include "wine/exception.h"
30 
32 
33 static const struct ddraw *exclusive_ddraw;
35 
36 /* Device identifier. Don't relay it to WineD3D */
38 {
39  "vga.dll", /* default 2D driver */
40  "DirectDraw HAL",
41  { { 0x00010001, 0x00010001 } },
42  0, 0, 0, 0,
43  /* a8373c10-7ac4-4deb-849a-009844d08b2d */
44  {0xa8373c10,0x7ac4,0x4deb, {0x84,0x9a,0x00,0x98,0x44,0xd0,0x8b,0x2d}},
45  0
46 };
47 
48 static struct enum_device_entry
49 {
50  char interface_name[100];
51  char device_name[100];
52  const GUID *device_guid;
54 } device_list7[] =
55 {
56  /* T&L HAL device */
57  {
58  "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D",
59  "Wine D3D7 T&L HAL",
60  &IID_IDirect3DTnLHalDevice,
61  0,
62  },
63 
64  /* HAL device */
65  {
66  "WINE Direct3D7 Hardware acceleration using WineD3D",
67  "Direct3D HAL",
68  &IID_IDirect3DHALDevice,
69  0,
70  },
71 
72  /* RGB device */
73  {
74  "WINE Direct3D7 RGB Software Emulation using WineD3D",
75  "Wine D3D7 RGB",
76  &IID_IDirect3DRGBDevice,
78  },
79 };
80 
82 
84 {
86 };
87 
88 static inline struct ddraw *impl_from_IDirectDraw(IDirectDraw *iface)
89 {
90  return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw_iface);
91 }
92 
93 static inline struct ddraw *impl_from_IDirectDraw2(IDirectDraw2 *iface)
94 {
95  return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw2_iface);
96 }
97 
98 static inline struct ddraw *impl_from_IDirectDraw4(IDirectDraw4 *iface)
99 {
100  return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw4_iface);
101 }
102 
103 static inline struct ddraw *impl_from_IDirectDraw7(IDirectDraw7 *iface)
104 {
105  return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw7_iface);
106 }
107 
108 static inline struct ddraw *impl_from_IDirect3D(IDirect3D *iface)
109 {
110  return CONTAINING_RECORD(iface, struct ddraw, IDirect3D_iface);
111 }
112 
113 static inline struct ddraw *impl_from_IDirect3D2(IDirect3D2 *iface)
114 {
115  return CONTAINING_RECORD(iface, struct ddraw, IDirect3D2_iface);
116 }
117 
118 static inline struct ddraw *impl_from_IDirect3D3(IDirect3D3 *iface)
119 {
120  return CONTAINING_RECORD(iface, struct ddraw, IDirect3D3_iface);
121 }
122 
123 static inline struct ddraw *impl_from_IDirect3D7(IDirect3D7 *iface)
124 {
125  return CONTAINING_RECORD(iface, struct ddraw, IDirect3D7_iface);
126 }
127 
129 {
130  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
131 
132  TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
133 
134  if (!riid)
135  {
136  *out = NULL;
137  return DDERR_INVALIDPARAMS;
138  }
139 
140  /* The refcount unit test revealed that an IDirect3D7 interface can only
141  * be queried from a DirectDraw object that was created as an IDirectDraw7
142  * interface. The older interfaces can query any IDirect3D version except
143  * 7, because they are all initially created as IDirectDraw. This isn't
144  * really crucial behavior, and messy to implement with the common
145  * creation function, so it has been left out here. */
146  if (IsEqualGUID(&IID_IDirectDraw7, riid)
148  {
150  TRACE("Returning IDirectDraw7 interface %p.\n", *out);
151  }
152  else if (IsEqualGUID(&IID_IDirectDraw4, riid))
153  {
155  TRACE("Returning IDirectDraw4 interface %p.\n", *out);
156  }
157  else if (IsEqualGUID(&IID_IDirectDraw2, riid))
158  {
160  TRACE("Returning IDirectDraw2 interface %p.\n", *out);
161  }
162  else if (IsEqualGUID(&IID_IDirectDraw, riid))
163  {
165  TRACE("Returning IDirectDraw interface %p.\n", *out);
166  }
167  else if (IsEqualGUID(&IID_IDirect3D7, riid))
168  {
169  ddraw->d3dversion = 7;
171  TRACE("Returning Direct3D7 interface %p.\n", *out);
172  }
173  else if (IsEqualGUID(&IID_IDirect3D3, riid))
174  {
175  ddraw->d3dversion = 3;
177  TRACE("Returning Direct3D3 interface %p.\n", *out);
178  }
179  else if (IsEqualGUID(&IID_IDirect3D2, riid))
180  {
181  ddraw->d3dversion = 2;
183  TRACE("Returning Direct3D2 interface %p.\n", *out);
184  }
185  else if (IsEqualGUID(&IID_IDirect3D, riid))
186  {
187  ddraw->d3dversion = 1;
189  TRACE("Returning Direct3D interface %p.\n", *out);
190  }
191  /* Unknown interface */
192  else
193  {
194  WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
195  *out = NULL;
196  return E_NOINTERFACE;
197  }
198 
199  IUnknown_AddRef((IUnknown *)*out);
200  return S_OK;
201 }
202 
203 static HRESULT WINAPI ddraw4_QueryInterface(IDirectDraw4 *iface, REFIID riid, void **object)
204 {
205  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
206 
207  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
208 
210 }
211 
212 static HRESULT WINAPI ddraw2_QueryInterface(IDirectDraw2 *iface, REFIID riid, void **object)
213 {
214  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
215 
216  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
217 
219 }
220 
221 static HRESULT WINAPI ddraw1_QueryInterface(IDirectDraw *iface, REFIID riid, void **object)
222 {
223  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
224 
225  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
226 
228 }
229 
230 static HRESULT WINAPI d3d7_QueryInterface(IDirect3D7 *iface, REFIID riid, void **object)
231 {
232  struct ddraw *ddraw = impl_from_IDirect3D7(iface);
233 
234  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
235 
237 }
238 
239 static HRESULT WINAPI d3d3_QueryInterface(IDirect3D3 *iface, REFIID riid, void **object)
240 {
241  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
242 
243  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
244 
246 }
247 
248 static HRESULT WINAPI d3d2_QueryInterface(IDirect3D2 *iface, REFIID riid, void **object)
249 {
250  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
251 
252  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
253 
255 }
256 
257 static HRESULT WINAPI d3d1_QueryInterface(IDirect3D *iface, REFIID riid, void **object)
258 {
259  struct ddraw *ddraw = impl_from_IDirect3D(iface);
260 
261  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
262 
264 }
265 
266 /*****************************************************************************
267  * IDirectDraw7::AddRef
268  *
269  * Increases the interfaces refcount, basically
270  *
271  * DDraw refcounting is a bit tricky. The different DirectDraw interface
272  * versions have individual refcounts, but the IDirect3D interfaces do not.
273  * All interfaces are from one object, that means calling QueryInterface on an
274  * IDirectDraw7 interface for an IDirectDraw4 interface does not create a new
275  * ddraw object.
276  *
277  * That means all AddRef and Release implementations of IDirectDrawX work
278  * with their own counter, and IDirect3DX::AddRef thunk to IDirectDraw (1),
279  * except of IDirect3D7 which thunks to IDirectDraw7
280  *
281  * Returns: The new refcount
282  *
283  *****************************************************************************/
285 {
286  struct ddraw *This = impl_from_IDirectDraw7(iface);
288 
289  TRACE("%p increasing refcount to %u.\n", This, ref);
290 
291  if(ref == 1) InterlockedIncrement(&This->numIfaces);
292 
293  return ref;
294 }
295 
296 static ULONG WINAPI ddraw4_AddRef(IDirectDraw4 *iface)
297 {
298  struct ddraw *This = impl_from_IDirectDraw4(iface);
300 
301  TRACE("%p increasing refcount to %u.\n", This, ref);
302 
303  if (ref == 1) InterlockedIncrement(&This->numIfaces);
304 
305  return ref;
306 }
307 
308 static ULONG WINAPI ddraw2_AddRef(IDirectDraw2 *iface)
309 {
310  struct ddraw *This = impl_from_IDirectDraw2(iface);
312 
313  TRACE("%p increasing refcount to %u.\n", This, ref);
314 
315  if (ref == 1) InterlockedIncrement(&This->numIfaces);
316 
317  return ref;
318 }
319 
320 static ULONG WINAPI ddraw1_AddRef(IDirectDraw *iface)
321 {
322  struct ddraw *This = impl_from_IDirectDraw(iface);
324 
325  TRACE("%p increasing refcount to %u.\n", This, ref);
326 
327  if (ref == 1) InterlockedIncrement(&This->numIfaces);
328 
329  return ref;
330 }
331 
332 static ULONG WINAPI d3d7_AddRef(IDirect3D7 *iface)
333 {
334  struct ddraw *This = impl_from_IDirect3D7(iface);
335 
336  TRACE("iface %p.\n", iface);
337 
338  return ddraw7_AddRef(&This->IDirectDraw7_iface);
339 }
340 
341 static ULONG WINAPI d3d3_AddRef(IDirect3D3 *iface)
342 {
343  struct ddraw *This = impl_from_IDirect3D3(iface);
344 
345  TRACE("iface %p.\n", iface);
346 
347  return ddraw1_AddRef(&This->IDirectDraw_iface);
348 }
349 
350 static ULONG WINAPI d3d2_AddRef(IDirect3D2 *iface)
351 {
352  struct ddraw *This = impl_from_IDirect3D2(iface);
353 
354  TRACE("iface %p.\n", iface);
355 
356  return ddraw1_AddRef(&This->IDirectDraw_iface);
357 }
358 
359 static ULONG WINAPI d3d1_AddRef(IDirect3D *iface)
360 {
361  struct ddraw *This = impl_from_IDirect3D(iface);
362 
363  TRACE("iface %p.\n", iface);
364 
365  return ddraw1_AddRef(&This->IDirectDraw_iface);
366 }
367 
368 static void ddraw_destroy_swapchain(struct ddraw *ddraw)
369 {
370  TRACE("Destroying the swapchain.\n");
371 
374 
375  if (!(ddraw->flags & DDRAW_NO3D))
376  {
377  UINT i;
378 
379  for (i = 0; i < ddraw->numConvertedDecls; ++i)
380  {
382  }
385 
387  {
388  ERR("Failed to uninit 3D.\n");
389  }
390  else
391  {
392  /* Free the d3d window if one was created. */
394  {
395  TRACE("Destroying the hidden render window %p.\n", ddraw->d3d_window);
397  ddraw->d3d_window = 0;
398  }
399  }
400 
402  }
403  else
404  {
406  }
407 
409 
410  TRACE("Swapchain destroyed.\n");
411 }
412 
413 /*****************************************************************************
414  * ddraw_destroy
415  *
416  * Destroys a ddraw object if all refcounts are 0. This is to share code
417  * between the IDirectDrawX::Release functions
418  *
419  * Params:
420  * This: DirectDraw object to destroy
421  *
422  *****************************************************************************/
423 static void ddraw_destroy(struct ddraw *This)
424 {
425  IDirectDraw7_SetCooperativeLevel(&This->IDirectDraw7_iface, NULL, DDSCL_NORMAL);
426  IDirectDraw7_RestoreDisplayMode(&This->IDirectDraw7_iface);
427 
428  /* Destroy the device window if we created one */
429  if(This->devicewindow != 0)
430  {
431  TRACE(" (%p) Destroying the device window %p\n", This, This->devicewindow);
432  DestroyWindow(This->devicewindow);
433  This->devicewindow = 0;
434  }
435 
437  list_remove(&This->ddraw_list_entry);
439 
440  if (This->wined3d_swapchain)
442  wined3d_device_decref(This->wined3d_device);
443  wined3d_decref(This->wined3d);
444 
445  if (This->d3ddevice)
446  This->d3ddevice->ddraw = NULL;
447 
448  /* Now free the object */
449  heap_free(This);
450 }
451 
452 /*****************************************************************************
453  * IDirectDraw7::Release
454  *
455  * Decreases the refcount. If the refcount falls to 0, the object is destroyed
456  *
457  * Returns: The new refcount
458  *****************************************************************************/
460 {
461  struct ddraw *This = impl_from_IDirectDraw7(iface);
463 
464  TRACE("%p decreasing refcount to %u.\n", This, ref);
465 
466  if (!ref && !InterlockedDecrement(&This->numIfaces))
468 
469  return ref;
470 }
471 
472 static ULONG WINAPI ddraw4_Release(IDirectDraw4 *iface)
473 {
474  struct ddraw *This = impl_from_IDirectDraw4(iface);
476 
477  TRACE("%p decreasing refcount to %u.\n", This, ref);
478 
479  if (!ref && !InterlockedDecrement(&This->numIfaces))
481 
482  return ref;
483 }
484 
485 static ULONG WINAPI ddraw2_Release(IDirectDraw2 *iface)
486 {
487  struct ddraw *This = impl_from_IDirectDraw2(iface);
489 
490  TRACE("%p decreasing refcount to %u.\n", This, ref);
491 
492  if (!ref && !InterlockedDecrement(&This->numIfaces))
494 
495  return ref;
496 }
497 
498 static ULONG WINAPI ddraw1_Release(IDirectDraw *iface)
499 {
500  struct ddraw *This = impl_from_IDirectDraw(iface);
502 
503  TRACE("%p decreasing refcount to %u.\n", This, ref);
504 
505  if (!ref && !InterlockedDecrement(&This->numIfaces))
507 
508  return ref;
509 }
510 
511 static ULONG WINAPI d3d7_Release(IDirect3D7 *iface)
512 {
513  struct ddraw *This = impl_from_IDirect3D7(iface);
514 
515  TRACE("iface %p.\n", iface);
516 
517  return ddraw7_Release(&This->IDirectDraw7_iface);
518 }
519 
520 static ULONG WINAPI d3d3_Release(IDirect3D3 *iface)
521 {
522  struct ddraw *This = impl_from_IDirect3D3(iface);
523 
524  TRACE("iface %p.\n", iface);
525 
526  return ddraw1_Release(&This->IDirectDraw_iface);
527 }
528 
529 static ULONG WINAPI d3d2_Release(IDirect3D2 *iface)
530 {
531  struct ddraw *This = impl_from_IDirect3D2(iface);
532 
533  TRACE("iface %p.\n", iface);
534 
535  return ddraw1_Release(&This->IDirectDraw_iface);
536 }
537 
538 static ULONG WINAPI d3d1_Release(IDirect3D *iface)
539 {
540  struct ddraw *This = impl_from_IDirect3D(iface);
541 
542  TRACE("iface %p.\n", iface);
543 
544  return ddraw1_Release(&This->IDirectDraw_iface);
545 }
546 
547 /*****************************************************************************
548  * IDirectDraw methods
549  *****************************************************************************/
550 
552 {
553  /* FIXME: This looks wrong, exclusive mode should imply a destination
554  * window. */
556  {
557  TRACE("Setting DDSCL_SETFOCUSWINDOW with an already set window, returning DDERR_HWNDALREADYSET.\n");
558  return DDERR_HWNDALREADYSET;
559  }
560 
562 
563  return DD_OK;
564 }
565 
567  struct wined3d_swapchain_desc *swapchain_desc)
568 {
569  HWND window = swapchain_desc->device_window;
570  HRESULT hr;
571 
572  TRACE("ddraw %p.\n", ddraw);
573 
574  if (!window || window == GetDesktopWindow())
575  {
576  window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "Hidden D3D Window",
578  NULL, NULL, NULL, NULL);
579  if (!window)
580  {
581  ERR("Failed to create window, last error %#x.\n", GetLastError());
582  return E_FAIL;
583  }
584 
585  ShowWindow(window, SW_HIDE); /* Just to be sure */
586  WARN("No window for the Direct3DDevice, created hidden window %p.\n", window);
587 
588  swapchain_desc->device_window = window;
589  }
590  else
591  {
592  TRACE("Using existing window %p for Direct3D rendering.\n", window);
593  }
595 
596  /* Set this NOW, otherwise creating the depth stencil surface will cause a
597  * recursive loop until ram or emulated video memory is full. */
599  hr = wined3d_device_init_3d(ddraw->wined3d_device, swapchain_desc);
600  if (FAILED(hr))
601  {
603  return hr;
604  }
605 
606  ddraw->declArraySize = 2;
607  if (!(ddraw->decls = heap_alloc_zero(ddraw->declArraySize * sizeof(*ddraw->decls))))
608  {
609  ERR("Error allocating an array for the converted vertex decls.\n");
610  ddraw->declArraySize = 0;
612  return E_OUTOFMEMORY;
613  }
614 
615  TRACE("Successfully initialized 3D.\n");
616 
617  return DD_OK;
618 }
619 
621 {
622  struct wined3d_swapchain_desc swapchain_desc;
623  struct wined3d_display_mode mode;
625 
627  {
628  ERR("Failed to get display mode.\n");
629  return hr;
630  }
631 
632  memset(&swapchain_desc, 0, sizeof(swapchain_desc));
633  swapchain_desc.backbuffer_width = mode.width;
634  swapchain_desc.backbuffer_height = mode.height;
635  swapchain_desc.backbuffer_format = mode.format_id;
637  swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_COPY;
638  swapchain_desc.device_window = window;
639  swapchain_desc.windowed = windowed;
641 
642  if (!(ddraw->flags & DDRAW_NO3D))
643  hr = ddraw_attach_d3d_device(ddraw, &swapchain_desc);
644  else
645  hr = wined3d_device_init_gdi(ddraw->wined3d_device, &swapchain_desc);
646 
647  if (FAILED(hr))
648  {
649  ERR("Failed to create swapchain, hr %#x.\n", hr);
650  return hr;
651  }
652 
654  {
655  ERR("Failed to get swapchain.\n");
656  return DDERR_INVALIDPARAMS;
657  }
658 
661 
662  if (ddraw->primary && ddraw->primary->palette)
663  wined3d_swapchain_set_palette(ddraw->wined3d_swapchain, ddraw->primary->palette->wined3d_palette);
664 
665  return DD_OK;
666 }
667 
668 /*****************************************************************************
669  * IDirectDraw7::RestoreDisplayMode
670  *
671  * Restores the display mode to what it was at creation time. Basically.
672  *
673  * Returns
674  * DD_OK on success
675  * DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
676  *
677  *****************************************************************************/
679 {
680  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
681  HRESULT hr;
682 
683  TRACE("iface %p.\n", iface);
684 
686 
687  if (!(ddraw->flags & DDRAW_RESTORE_MODE))
688  {
690  return DD_OK;
691  }
692 
694  {
696  return DDERR_NOEXCLUSIVEMODE;
697  }
698 
701 
703 
705 
706  return hr;
707 }
708 
709 static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
710 {
711  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
712 
713  TRACE("iface %p.\n", iface);
714 
716 }
717 
718 static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
719 {
720  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
721 
722  TRACE("iface %p.\n", iface);
723 
725 }
726 
727 static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
728 {
729  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
730 
731  TRACE("iface %p.\n", iface);
732 
734 }
735 
736 /*****************************************************************************
737  * IDirectDraw7::SetCooperativeLevel
738  *
739  * Sets the cooperative level for the DirectDraw object, and the window
740  * assigned to it. The cooperative level determines the general behavior
741  * of the DirectDraw application
742  *
743  * Warning: This is quite tricky, as it's not really documented which
744  * cooperative levels can be combined with each other. If a game fails
745  * after this function, try to check the cooperative levels passed on
746  * Windows, and if it returns something different.
747  *
748  * If you think that this function caused the failure because it writes a
749  * fixme, be sure to run again with a +ddraw trace.
750  *
751  * What is known about cooperative levels (See the ddraw modes test):
752  * DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN.
753  * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE.
754  * Unlike what msdn claims, DDSCL_NORMAL | DDSCL_FULLSCREEN is allowed.
755  * DDSCL_SETFOCUSWINDOW can be passed only in DDSCL_NORMAL mode, but after that
756  * DDSCL_EXCLUSIVE can be activated.
757  * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES or
758  * DDSCL_CREATEDEVICEWINDOW.
759  *
760  * Handled flags: DDSCL_NORMAL, DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE,
761  * DDSCL_CREATEDEVICEWINDOW, DDSCL_SETDEVICEWINDOW
762  * DDSCL_SETFOCUSWINDOW (partially),
763  * DDSCL_MULTITHREADED (work in progress)
764  * DDSCL_FPUPRESERVE (see device.c)
765  *
766  * Unsure about this: DDSCL_FPUSETUP
767  *
768  * These don't seem very important for wine:
769  * DDSCL_ALLOWREBOOT, DDSCL_NOWINDOWCHANGES, DDSCL_ALLOWMODEX
770  *
771  * Returns:
772  * DD_OK if the cooperative level was set successfully
773  * DDERR_INVALIDPARAMS if the passed cooperative level combination is invalid
774  * DDERR_HWNDALREADYSET if DDSCL_SETFOCUSWINDOW is passed in exclusive mode
775  * (Probably others too, have to investigate)
776  *
777  *****************************************************************************/
779  DWORD cooplevel, BOOL restore_mode_on_normal)
780 {
781  struct wined3d_rendertarget_view *rtv = NULL, *dsv = NULL;
782  struct wined3d_stateblock *stateblock;
783  BOOL restore_state = FALSE;
784  HRESULT hr;
785 
786  TRACE("ddraw %p, window %p, flags %#x, restore_mode_on_normal %x.\n", ddraw, window, cooplevel,
787  restore_mode_on_normal);
788  DDRAW_dump_cooperativelevel(cooplevel);
789 
791 
793  {
794  WARN("Recursive call, returning DD_OK.\n");
795  hr = DD_OK;
796  goto done;
797  }
799 
800  /* Tests suggest that we need one of them: */
801  if(!(cooplevel & (DDSCL_SETFOCUSWINDOW |
802  DDSCL_NORMAL |
803  DDSCL_EXCLUSIVE )))
804  {
805  TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n");
807  goto done;
808  }
809 
810  if ((cooplevel & DDSCL_CREATEDEVICEWINDOW) && !(cooplevel & DDSCL_EXCLUSIVE))
811  {
812  WARN("DDSCL_CREATEDEVICEWINDOW requires DDSCL_EXCLUSIVE.\n");
814  goto done;
815  }
816 
817  /* Handle those levels first which set various hwnds */
818  if ((cooplevel & DDSCL_SETFOCUSWINDOW) && !(cooplevel & DDSCL_CREATEDEVICEWINDOW))
819  {
820  /* This isn't compatible with a lot of flags */
821  if (cooplevel & (DDSCL_MULTITHREADED
827  | DDSCL_NORMAL
829  | DDSCL_FULLSCREEN))
830  {
831  WARN("Called with incompatible flags, returning DDERR_INVALIDPARAMS.\n");
833  goto done;
834  }
835 
837  goto done;
838  }
839 
840  if (cooplevel & DDSCL_EXCLUSIVE)
841  {
842  if (!(cooplevel & DDSCL_FULLSCREEN) || !(window || (cooplevel & DDSCL_CREATEDEVICEWINDOW)))
843  {
844  WARN("DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN and a window.\n");
846  goto done;
847  }
848 
849  if (cooplevel & DDSCL_CREATEDEVICEWINDOW)
850  {
851  HWND device_window;
852 
853  if (!ddraw->focuswindow && !(cooplevel & DDSCL_SETFOCUSWINDOW))
854  {
855  WARN("No focus window set.\n");
857  goto done;
858  }
859 
860  device_window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "DirectDrawDeviceWnd",
862  NULL, NULL, NULL, NULL);
863  if (!device_window)
864  {
865  ERR("Failed to create window, last error %#x.\n", GetLastError());
866  hr = E_FAIL;
867  goto done;
868  }
869 
870  ShowWindow(device_window, SW_SHOW);
871  TRACE("Created a device window %p.\n", device_window);
872 
873  /* Native apparently leaks the created device window if setting the
874  * focus window below fails. */
876  ddraw->devicewindow = device_window;
877 
878  if (cooplevel & DDSCL_SETFOCUSWINDOW)
879  {
880  if (!window)
881  {
882  hr = DDERR_NOHWND;
883  goto done;
884  }
885 
887  goto done;
888  }
889 
890  window = device_window;
891  }
892  }
893  else
894  {
899  }
900 
902  {
905 
906  if (cooplevel & DDSCL_FULLSCREEN)
907  {
908  struct wined3d_display_mode display_mode;
909 
912  display_mode.width, display_mode.height);
913  }
914  }
915 
916  if ((cooplevel & DDSCL_EXCLUSIVE) && exclusive_window != window)
917  {
920  }
921 
924 
926  {
927  if (!(ddraw->flags & DDRAW_NO3D))
928  {
929  restore_state = TRUE;
930 
932  {
933  ERR("Failed to create stateblock, hr %#x.\n", hr);
934  goto done;
935  }
936 
937  wined3d_stateblock_capture(stateblock);
939  /* Rendering to ddraw->wined3d_frontbuffer. */
941  rtv = NULL;
942  else if (rtv)
944 
947  }
948 
950  }
951 
952  if (FAILED(hr = ddraw_create_swapchain(ddraw, window, !(cooplevel & DDSCL_FULLSCREEN))))
953  ERR("Failed to create swapchain, hr %#x.\n", hr);
954 
955  if (restore_state)
956  {
957  if (dsv)
958  {
961  }
962 
963  if (rtv)
964  {
967  }
968 
969  wined3d_stateblock_apply(stateblock);
970  wined3d_stateblock_decref(stateblock);
971  }
972 
973  if (!(cooplevel & DDSCL_EXCLUSIVE) && (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
974  && restore_mode_on_normal)
975  {
977  if (FAILED(hr))
978  ERR("RestoreDisplayMode failed\n");
979  }
980 
982  && (window != ddraw->dest_window || !(cooplevel & DDSCL_EXCLUSIVE)))
984 
985  if ((cooplevel & DDSCL_EXCLUSIVE)
987  {
989  if (FAILED(hr))
990  {
991  ERR("Failed to acquire focus window, hr %#x.\n", hr);
992  goto done;
993  }
994  }
995 
996  /* Unhandled flags */
997  if (cooplevel & DDSCL_ALLOWREBOOT)
998  WARN("Unhandled flag DDSCL_ALLOWREBOOT, harmless\n");
999  if (cooplevel & DDSCL_ALLOWMODEX)
1000  WARN("Unhandled flag DDSCL_ALLOWMODEX, harmless\n");
1001  if (cooplevel & DDSCL_FPUSETUP)
1002  WARN("Unhandled flag DDSCL_FPUSETUP, harmless\n");
1003 
1004  if (cooplevel & DDSCL_EXCLUSIVE)
1006  else if (exclusive_ddraw == ddraw)
1008 
1009  /* Store the cooperative_level */
1010  ddraw->cooperative_level = cooplevel;
1012 
1013  TRACE("SetCooperativeLevel returning DD_OK\n");
1014  hr = DD_OK;
1015 done:
1018 
1019  return hr;
1020 }
1021 
1023 {
1024  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1025 
1026  TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1027 
1029 }
1030 
1032 {
1033  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1034 
1035  TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1036 
1038 }
1039 
1041 {
1042  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1043 
1044  TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1045 
1047 }
1048 
1050 {
1051  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1052  HRESULT hr;
1053 
1054  TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1055 
1057  if (SUCCEEDED(hr))
1059  return hr;
1060 }
1061 
1062 /*****************************************************************************
1063  * IDirectDraw7::SetDisplayMode
1064  *
1065  * Sets the display screen resolution, color depth and refresh frequency
1066  * when in fullscreen mode (in theory).
1067  * Possible return values listed in the SDK suggest that this method fails
1068  * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets
1069  * the display mode in DDSCL_NORMAL mode without an hwnd specified.
1070  * It seems to be valid to pass 0 for With and Height, this has to be tested
1071  * It could mean that the current video mode should be left as-is. (But why
1072  * call it then?)
1073  *
1074  * Params:
1075  * Height, Width: Screen dimension
1076  * BPP: Color depth in Bits per pixel
1077  * Refreshrate: Screen refresh rate
1078  * Flags: Other stuff
1079  *
1080  * Returns
1081  * DD_OK on success
1082  *
1083  *****************************************************************************/
1085  DWORD bpp, DWORD refresh_rate, DWORD flags)
1086 {
1087  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1088  struct wined3d_display_mode mode;
1090  HRESULT hr;
1091 
1092  TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
1093  iface, width, height, bpp, refresh_rate, flags);
1094 
1095  if (force_refresh_rate != 0)
1096  {
1097  TRACE("ForceRefreshRate overriding passed-in refresh rate (%u Hz) to %u Hz\n",
1100  }
1101 
1103 
1105  {
1107  return DDERR_NOEXCLUSIVEMODE;
1108  }
1109 
1110  if (!width || !height)
1111  {
1112  /* It looks like Need for Speed Porsche Unleashed expects DD_OK here. */
1114  return DD_OK;
1115  }
1116 
1117  switch (bpp)
1118  {
1119  case 8: format = WINED3DFMT_P8_UINT; break;
1120  case 15: format = WINED3DFMT_B5G5R5X1_UNORM; break;
1121  case 16: format = WINED3DFMT_B5G6R5_UNORM; break;
1122  case 24: format = WINED3DFMT_B8G8R8_UNORM; break;
1123  case 32: format = WINED3DFMT_B8G8R8X8_UNORM; break;
1124  default: format = WINED3DFMT_UNKNOWN; break;
1125  }
1126 
1127  mode.width = width;
1128  mode.height = height;
1129  mode.refresh_rate = refresh_rate;
1130  mode.format_id = format;
1131  mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
1132 
1133  /* TODO: The possible return values from msdn suggest that the screen mode
1134  * can't be changed if a surface is locked or some drawing is in progress. */
1136  {
1137  if (ddraw->primary)
1138  {
1139  DDSURFACEDESC2 *surface_desc = &ddraw->primary->surface_desc;
1140 
1142  surface_desc->dwWidth, surface_desc->dwHeight, mode.format_id, WINED3D_MULTISAMPLE_NONE, 0)))
1143  ERR("Failed to resize buffers, hr %#x.\n", hr);
1144  else
1145  ddrawformat_from_wined3dformat(&ddraw->primary->surface_desc.u4.ddpfPixelFormat, mode.format_id);
1146  }
1148  }
1149 
1151 
1153 
1154  switch (hr)
1155  {
1157  default: return hr;
1158  }
1159 }
1160 
1163 {
1164  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1165 
1166  TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
1167  iface, width, height, bpp, refresh_rate, flags);
1168 
1169  return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags);
1170 }
1171 
1172 static HRESULT WINAPI ddraw2_SetDisplayMode(IDirectDraw2 *iface,
1173  DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
1174 {
1175  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1176 
1177  TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
1178  iface, width, height, bpp, refresh_rate, flags);
1179 
1180  return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags);
1181 }
1182 
1184 {
1185  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1186 
1187  TRACE("iface %p, width %u, height %u, bpp %u.\n", iface, width, height, bpp);
1188 
1190 }
1191 
1193 {
1194  memset(caps1, 0, sizeof(*caps1));
1195  caps1->dwSize = sizeof(*caps1);
1196  caps1->dwFlags = D3DDD_COLORMODEL
1197  | D3DDD_DEVCAPS
1199  | D3DDD_BCLIPPING
1201  | D3DDD_LINECAPS
1202  | D3DDD_TRICAPS
1207  caps1->dcmColorModel = D3DCOLOR_RGB;
1208  caps1->dwDevCaps = caps7->dwDevCaps;
1209  caps1->dtcTransformCaps.dwSize = sizeof(caps1->dtcTransformCaps);
1211  caps1->bClipping = TRUE;
1212  caps1->dlcLightingCaps.dwSize = sizeof(caps1->dlcLightingCaps);
1219  caps1->dpcLineCaps = caps7->dpcLineCaps;
1220  caps1->dpcTriCaps = caps7->dpcTriCaps;
1223  caps1->dwMaxBufferSize = 0;
1224  caps1->dwMaxVertexCount = 65536;
1225  caps1->dwMinTextureWidth = caps7->dwMinTextureWidth;
1226  caps1->dwMinTextureHeight = caps7->dwMinTextureHeight;
1227  caps1->dwMaxTextureWidth = caps7->dwMaxTextureWidth;
1228  caps1->dwMaxTextureHeight = caps7->dwMaxTextureHeight;
1229  caps1->dwMinStippleWidth = 1;
1230  caps1->dwMinStippleHeight = 1;
1231  caps1->dwMaxStippleWidth = 32;
1232  caps1->dwMaxStippleHeight = 32;
1233  caps1->dwMaxTextureRepeat = caps7->dwMaxTextureRepeat;
1235  caps1->dwMaxAnisotropy = caps7->dwMaxAnisotropy;
1236  caps1->dvGuardBandLeft = caps7->dvGuardBandLeft;
1237  caps1->dvGuardBandTop = caps7->dvGuardBandTop;
1238  caps1->dvGuardBandRight = caps7->dvGuardBandRight;
1239  caps1->dvGuardBandBottom = caps7->dvGuardBandBottom;
1240  caps1->dvExtentsAdjust = caps7->dvExtentsAdjust;
1241  caps1->dwStencilCaps = caps7->dwStencilCaps;
1242  caps1->dwFVFCaps = caps7->dwFVFCaps;
1243  caps1->dwTextureOpCaps = caps7->dwTextureOpCaps;
1246 }
1247 
1249 {
1250  WINED3DCAPS wined3d_caps;
1251  HRESULT hr;
1252 
1253  TRACE("ddraw %p, caps %p.\n", ddraw, caps);
1254 
1255  memset(&wined3d_caps, 0, sizeof(wined3d_caps));
1256 
1260  if (FAILED(hr))
1261  {
1262  WARN("Failed to get device caps, hr %#x.\n", hr);
1263  return hr;
1264  }
1265 
1266  caps->dwDevCaps = wined3d_caps.DevCaps;
1267  caps->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps;
1268  caps->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps;
1269  caps->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps;
1270  caps->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps;
1271  caps->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps;
1272  caps->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps;
1273  caps->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps;
1274  caps->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps;
1275  caps->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps;
1277 
1278  caps->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
1279  caps->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
1280 
1281  caps->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
1282  caps->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio;
1283  caps->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy;
1284  caps->dvMaxVertexW = wined3d_caps.MaxVertexW;
1285 
1286  caps->dvGuardBandLeft = wined3d_caps.GuardBandLeft;
1287  caps->dvGuardBandTop = wined3d_caps.GuardBandTop;
1288  caps->dvGuardBandRight = wined3d_caps.GuardBandRight;
1289  caps->dvGuardBandBottom = wined3d_caps.GuardBandBottom;
1290 
1291  caps->dvExtentsAdjust = wined3d_caps.ExtentsAdjust;
1292  caps->dwStencilCaps = wined3d_caps.StencilCaps;
1293 
1294  caps->dwFVFCaps = wined3d_caps.FVFCaps;
1295  caps->dwTextureOpCaps = wined3d_caps.TextureOpCaps;
1296 
1297  caps->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps;
1298  caps->dwMaxActiveLights = wined3d_caps.MaxActiveLights;
1299 
1300  /* Remove all non-d3d7 caps */
1301  caps->dwDevCaps &= (
1309 
1310  caps->dwStencilCaps &= (
1314 
1315  /* FVF caps ?*/
1316 
1317  caps->dwTextureOpCaps &= (
1326 
1327  caps->dwVertexProcessingCaps &= (
1330 
1331  caps->dpcLineCaps.dwMiscCaps &= (
1335 
1336  caps->dpcLineCaps.dwRasterCaps &= (
1345 
1346  caps->dpcLineCaps.dwZCmpCaps &= (
1350 
1351  caps->dpcLineCaps.dwSrcBlendCaps &= (
1357 
1358  caps->dpcLineCaps.dwDestBlendCaps &= (
1364 
1365  caps->dpcLineCaps.dwAlphaCmpCaps &= (
1369 
1370  caps->dpcLineCaps.dwShadeCaps &= (
1378 
1379  caps->dpcLineCaps.dwTextureCaps &= (
1384 
1385  caps->dpcLineCaps.dwTextureFilterCaps &= (
1392 
1396 
1398  {
1399  /* DirectX7 always has the np2 flag set, no matter what the card
1400  * supports. Some old games (Rollcage) check the caps incorrectly.
1401  * If wined3d supports nonpow2 textures it also has np2 conditional
1402  * support. */
1404  }
1405 
1406  /* Fill the missing members, and do some fixup */
1407  caps->dpcLineCaps.dwSize = sizeof(caps->dpcLineCaps);
1416  caps->dpcLineCaps.dwStippleWidth = 32;
1417  caps->dpcLineCaps.dwStippleHeight = 32;
1418  /* Use the same for the TriCaps */
1419  caps->dpcTriCaps = caps->dpcLineCaps;
1420 
1423  caps->dwMinTextureWidth = 1;
1424  caps->dwMinTextureHeight = 1;
1425 
1426  /* Convert DWORDs safely to WORDs */
1427  caps->wMaxTextureBlendStages = min(wined3d_caps.MaxTextureBlendStages, 0xffff);
1428  caps->wMaxSimultaneousTextures = min(wined3d_caps.MaxSimultaneousTextures, 0xffff);
1430  caps->wMaxVertexBlendMatrices = min(wined3d_caps.MaxVertexBlendMatrices, 0xffff);
1431 
1432  caps->deviceGUID = IID_IDirect3DTnLHalDevice;
1433 
1434  caps->dwReserved1 = 0;
1435  caps->dwReserved2 = 0;
1436  caps->dwReserved3 = 0;
1437  caps->dwReserved4 = 0;
1438 
1439  return DD_OK;
1440 }
1441 
1443 {
1444  DDCAPS *caps = ctx;
1445 
1446  switch (format->u1.dwZBufferBitDepth)
1447  {
1448  case 8:
1449  caps->dwZBufferBitDepths |= DDBD_8;
1450  break;
1451  case 16:
1452  caps->dwZBufferBitDepths |= DDBD_16;
1453  break;
1454  case 24:
1455  caps->dwZBufferBitDepths |= DDBD_24;
1456  break;
1457  case 32:
1458  caps->dwZBufferBitDepths |= DDBD_32;
1459  break;
1460  }
1461  return D3DENUMRET_OK;
1462 }
1463 
1464 /*****************************************************************************
1465  * IDirectDraw7::GetCaps
1466  *
1467  * Returns the drives capabilities
1468  *
1469  * Used for version 1, 2, 4 and 7
1470  *
1471  * Params:
1472  * DriverCaps: Structure to write the Hardware accelerated caps to
1473  * HelCaps: Structure to write the emulation caps to
1474  *
1475  * Returns
1476  * This implementation returns DD_OK only
1477  *
1478  *****************************************************************************/
1479 static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DDCAPS *HELCaps)
1480 {
1481  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1482  DDCAPS caps;
1483  WINED3DCAPS winecaps;
1484  HRESULT hr;
1485  DDSCAPS2 ddscaps = {0, 0, 0, {0}};
1486 
1487  TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, DriverCaps, HELCaps);
1488 
1489  /* One structure must be != NULL */
1490  if (!DriverCaps && !HELCaps)
1491  {
1492  WARN("Invalid parameters.\n");
1493  return DDERR_INVALIDPARAMS;
1494  }
1495 
1496  memset(&caps, 0, sizeof(caps));
1497  memset(&winecaps, 0, sizeof(winecaps));
1498  caps.dwSize = sizeof(caps);
1499 
1502  if (FAILED(hr))
1503  {
1504  WARN("Failed to get device caps, %#x.\n", hr);
1506  return hr;
1507  }
1508 
1509  hr = IDirectDraw7_GetAvailableVidMem(iface, &ddscaps, &caps.dwVidMemTotal, &caps.dwVidMemFree);
1510  if (FAILED(hr))
1511  {
1512  WARN("IDirectDraw7::GetAvailableVidMem failed\n");
1514  return hr;
1515  }
1516 
1517  hr = IDirectDraw7_GetFourCCCodes(iface, &caps.dwNumFourCCCodes, NULL);
1519  if (FAILED(hr))
1520  {
1521  WARN("IDirectDraw7::GetFourCCCodes failed\n");
1522  return hr;
1523  }
1524 
1525  caps.dwCaps = winecaps.ddraw_caps.caps;
1526  caps.dwCaps2 = winecaps.ddraw_caps.caps2;
1527  caps.dwCKeyCaps = winecaps.ddraw_caps.color_key_caps;
1528  caps.dwFXCaps = winecaps.ddraw_caps.fx_caps;
1529  caps.dwPalCaps = DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE;
1530  caps.ddsCaps.dwCaps = winecaps.ddraw_caps.dds_caps;
1531  caps.dwSVBCaps = winecaps.ddraw_caps.svb_caps;
1532  caps.dwSVBCKeyCaps = winecaps.ddraw_caps.svb_color_key_caps;
1533  caps.dwSVBFXCaps = winecaps.ddraw_caps.svb_fx_caps;
1534  caps.dwVSBCaps = winecaps.ddraw_caps.vsb_caps;
1535  caps.dwVSBCKeyCaps = winecaps.ddraw_caps.vsb_color_key_caps;
1536  caps.dwVSBFXCaps = winecaps.ddraw_caps.vsb_fx_caps;
1537  caps.dwSSBCaps = winecaps.ddraw_caps.ssb_caps;
1538  caps.dwSSBCKeyCaps = winecaps.ddraw_caps.ssb_color_key_caps;
1539  caps.dwSSBFXCaps = winecaps.ddraw_caps.ssb_fx_caps;
1540 
1541  caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
1542  caps.dwAlignStrideAlign = DDRAW_STRIDE_ALIGNMENT;
1543 
1544  caps.ddsOldCaps.dwCaps = caps.ddsCaps.dwCaps;
1545 
1546  IDirect3D7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, &IID_IDirect3DHALDevice, enum_zbuffer, &caps);
1547 
1548  if(DriverCaps)
1549  {
1550  DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
1551  if (TRACE_ON(ddraw))
1552  {
1553  TRACE("Driver Caps :\n");
1554  DDRAW_dump_DDCAPS(DriverCaps);
1555  }
1556 
1557  }
1558  if(HELCaps)
1559  {
1560  DD_STRUCT_COPY_BYSIZE(HELCaps, &caps);
1561  if (TRACE_ON(ddraw))
1562  {
1563  TRACE("HEL Caps :\n");
1564  DDRAW_dump_DDCAPS(HELCaps);
1565  }
1566  }
1567 
1568  return DD_OK;
1569 }
1570 
1571 static HRESULT WINAPI ddraw4_GetCaps(IDirectDraw4 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1572 {
1573  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1574 
1575  TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1576 
1577  return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1578 }
1579 
1580 static HRESULT WINAPI ddraw2_GetCaps(IDirectDraw2 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1581 {
1582  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1583 
1584  TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1585 
1586  return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1587 }
1588 
1589 static HRESULT WINAPI ddraw1_GetCaps(IDirectDraw *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1590 {
1591  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1592 
1593  TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1594 
1595  return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1596 }
1597 
1598 /*****************************************************************************
1599  * IDirectDraw7::Compact
1600  *
1601  * No idea what it does, MSDN says it's not implemented.
1602  *
1603  * Returns
1604  * DD_OK, but this is unchecked
1605  *
1606  *****************************************************************************/
1608 {
1609  TRACE("iface %p.\n", iface);
1610 
1611  return DD_OK;
1612 }
1613 
1614 static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface)
1615 {
1616  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1617 
1618  TRACE("iface %p.\n", iface);
1619 
1621 }
1622 
1623 static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface)
1624 {
1625  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1626 
1627  TRACE("iface %p.\n", iface);
1628 
1630 }
1631 
1632 static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface)
1633 {
1634  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1635 
1636  TRACE("iface %p.\n", iface);
1637 
1639 }
1640 
1641 /*****************************************************************************
1642  * IDirectDraw7::GetDisplayMode
1643  *
1644  * Returns information about the current display mode
1645  *
1646  * Exists in versions 1, 2, 4 and 7
1647  *
1648  * Params:
1649  * DDSD: Address of a surface description structure to write the info to
1650  *
1651  * Returns
1652  * DD_OK
1653  *
1654  *****************************************************************************/
1656 {
1657  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1658  struct wined3d_display_mode mode;
1659  HRESULT hr;
1660 
1661  TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
1662 
1663  /* This seems sane */
1664  if (!DDSD || (DDSD->dwSize != sizeof(DDSURFACEDESC) && DDSD->dwSize != sizeof(DDSURFACEDESC2)))
1665  return DDERR_INVALIDPARAMS;
1666 
1668 
1670  {
1671  ERR("Failed to get display mode, hr %#x.\n", hr);
1673  return hr;
1674  }
1675 
1676  memset(DDSD, 0, DDSD->dwSize);
1677  DDSD->dwSize = sizeof(*DDSD);
1679  DDSD->dwWidth = mode.width;
1680  DDSD->dwHeight = mode.height;
1681  DDSD->u2.dwRefreshRate = 60;
1682  DDSD->ddsCaps.dwCaps = 0;
1683  DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat);
1684  ddrawformat_from_wined3dformat(&DDSD->u4.ddpfPixelFormat, mode.format_id);
1685  DDSD->u1.lPitch = mode.width * DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount / 8;
1686 
1687  if(TRACE_ON(ddraw))
1688  {
1689  TRACE("Returning surface desc :\n");
1691  }
1692 
1694 
1695  return DD_OK;
1696 }
1697 
1698 static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *surface_desc)
1699 {
1700  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1701 
1702  TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1703 
1704  return ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, surface_desc);
1705 }
1706 
1707 static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *surface_desc)
1708 {
1709  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1710  HRESULT hr;
1711 
1712  TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1713 
1715  if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
1716  return hr;
1717 }
1718 
1719 static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *surface_desc)
1720 {
1721  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1722  HRESULT hr;
1723 
1724  TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1725 
1727  if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
1728  return hr;
1729 }
1730 
1731 /*****************************************************************************
1732  * IDirectDraw7::GetFourCCCodes
1733  *
1734  * Returns an array of supported FourCC codes.
1735  *
1736  * Exists in versions 1, 2, 4 and 7
1737  *
1738  * Params:
1739  * NumCodes: Contains the number of Codes that Codes can carry. Returns the number
1740  * of enumerated codes
1741  * Codes: Pointer to an array of DWORDs where the supported codes are written
1742  * to
1743  *
1744  * Returns
1745  * Always returns DD_OK, as it's a stub for now
1746  *
1747  *****************************************************************************/
1748 static HRESULT WINAPI ddraw7_GetFourCCCodes(IDirectDraw7 *iface, DWORD *NumCodes, DWORD *Codes)
1749 {
1750  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1751  static const enum wined3d_format_id formats[] =
1752  {
1756  };
1757  struct wined3d_display_mode mode;
1758  DWORD count = 0, i, outsize;
1759  HRESULT hr;
1760 
1761  TRACE("iface %p, codes_count %p, codes %p.\n", iface, NumCodes, Codes);
1762 
1764  {
1765  ERR("Failed to get display mode, hr %#x.\n", hr);
1766  return hr;
1767  }
1768 
1769  outsize = NumCodes && Codes ? *NumCodes : 0;
1770 
1771  for (i = 0; i < ARRAY_SIZE(formats); ++i)
1772  {
1774  mode.format_id, 0, WINED3D_RTYPE_TEXTURE_2D, formats[i])))
1775  {
1776  if (count < outsize)
1777  Codes[count] = formats[i];
1778  ++count;
1779  }
1780  }
1781  if(NumCodes) {
1782  TRACE("Returning %u FourCC codes\n", count);
1783  *NumCodes = count;
1784  }
1785 
1786  return DD_OK;
1787 }
1788 
1789 static HRESULT WINAPI ddraw4_GetFourCCCodes(IDirectDraw4 *iface, DWORD *codes_count, DWORD *codes)
1790 {
1791  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1792 
1793  TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1794 
1795  return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1796 }
1797 
1798 static HRESULT WINAPI ddraw2_GetFourCCCodes(IDirectDraw2 *iface, DWORD *codes_count, DWORD *codes)
1799 {
1800  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1801 
1802  TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1803 
1804  return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1805 }
1806 
1807 static HRESULT WINAPI ddraw1_GetFourCCCodes(IDirectDraw *iface, DWORD *codes_count, DWORD *codes)
1808 {
1809  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1810 
1811  TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1812 
1813  return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1814 }
1815 
1817 {
1818  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1819  struct wined3d_display_mode mode;
1820  HRESULT hr;
1821 
1822  TRACE("iface %p, frequency %p.\n", iface, frequency);
1823 
1827  if (FAILED(hr))
1828  {
1829  WARN("Failed to get display mode, hr %#x.\n", hr);
1830  return hr;
1831  }
1832 
1833  *frequency = mode.refresh_rate;
1834 
1835  return DD_OK;
1836 }
1837 
1839 {
1840  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1841 
1842  TRACE("iface %p, frequency %p.\n", iface, frequency);
1843 
1845 }
1846 
1848 {
1849  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1850 
1851  TRACE("iface %p, frequency %p.\n", iface, frequency);
1852 
1854 }
1855 
1857 {
1858  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1859 
1860  TRACE("iface %p, frequency %p.\n", iface, frequency);
1861 
1863 }
1864 
1866 {
1867  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1868  struct wined3d_raster_status raster_status;
1869  HRESULT hr;
1870 
1871  TRACE("iface %p, status %p.\n", iface, status);
1872 
1873  if(!status)
1874  return DDERR_INVALIDPARAMS;
1875 
1879  if (FAILED(hr))
1880  {
1881  WARN("Failed to get raster status, hr %#x.\n", hr);
1882  return hr;
1883  }
1884 
1885  *status = raster_status.in_vblank;
1886 
1887  return DD_OK;
1888 }
1889 
1891 {
1892  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1893 
1894  TRACE("iface %p, status %p.\n", iface, status);
1895 
1897 }
1898 
1900 {
1901  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1902 
1903  TRACE("iface %p, status %p.\n", iface, status);
1904 
1906 }
1907 
1909 {
1910  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1911 
1912  TRACE("iface %p, status %p.\n", iface, status);
1913 
1915 }
1916 
1917 /*****************************************************************************
1918  * IDirectDraw7::GetAvailableVidMem
1919  *
1920  * Returns the total and free video memory
1921  *
1922  * Params:
1923  * caps: Specifies the memory type asked for
1924  * total: Pointer to a DWORD to be filled with the total memory
1925  * free: Pointer to a DWORD to be filled with the free memory
1926  *
1927  * Returns
1928  * DD_OK on success
1929  * DDERR_INVALIDPARAMS if free and total are NULL
1930  *
1931  *****************************************************************************/
1933  DWORD *free)
1934 {
1935  unsigned int framebuffer_size, total_vidmem, free_vidmem;
1936  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1937  struct wined3d_display_mode mode;
1938  HRESULT hr = DD_OK;
1939 
1940  TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1941 
1942  if (!total && !free)
1943  return DDERR_INVALIDPARAMS;
1944 
1945  if (TRACE_ON(ddraw))
1946  {
1947  TRACE("Asked for memory with description: ");
1948  DDRAW_dump_DDSCAPS2(caps);
1949  }
1951 
1952  /* Todo: System memory vs local video memory vs non-local video memory
1953  * The MSDN also mentions differences between texture memory and other
1954  * resources, but that's not important
1955  */
1956 
1957  /* Some applications (e.g. 3DMark 2000) assume that the reported amount of
1958  * video memory doesn't include the memory used by the default framebuffer.
1959  */
1961  {
1962  WARN("Failed to get display mode, hr %#x.\n", hr);
1964  return hr;
1965  }
1967  mode.format_id, mode.width);
1968  framebuffer_size *= mode.height;
1969 
1970  if (free)
1971  {
1973  *free = framebuffer_size > free_vidmem ? 0 : free_vidmem - framebuffer_size;
1974  TRACE("Free video memory %#x.\n", *free);
1975  }
1976 
1977  if (total)
1978  {
1979  struct wined3d_adapter_identifier desc = {0};
1980 
1982  total_vidmem = min(UINT_MAX, desc.video_memory);
1983  *total = framebuffer_size > total_vidmem ? 0 : total_vidmem - framebuffer_size;
1984  TRACE("Total video memory %#x.\n", *total);
1985  }
1986 
1988 
1989  return hr;
1990 }
1991 
1992 static HRESULT WINAPI ddraw4_GetAvailableVidMem(IDirectDraw4 *iface,
1993  DDSCAPS2 *caps, DWORD *total, DWORD *free)
1994 {
1995  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1996 
1997  TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1998 
1999  return ddraw7_GetAvailableVidMem(&ddraw->IDirectDraw7_iface, caps, total, free);
2000 }
2001 
2002 static HRESULT WINAPI ddraw2_GetAvailableVidMem(IDirectDraw2 *iface,
2003  DDSCAPS *caps, DWORD *total, DWORD *free)
2004 {
2005  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2006  DDSCAPS2 caps2;
2007 
2008  TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
2009 
2010  DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
2011  return ddraw7_GetAvailableVidMem(&ddraw->IDirectDraw7_iface, &caps2, total, free);
2012 }
2013 
2014 /*****************************************************************************
2015  * IDirectDraw7::Initialize
2016  *
2017  * Initializes a DirectDraw interface.
2018  *
2019  * Params:
2020  * GUID: Interface identifier. Well, don't know what this is really good
2021  * for
2022  *
2023  * Returns
2024  * Returns DD_OK on the first call,
2025  * DDERR_ALREADYINITIALIZED on repeated calls
2026  *
2027  *****************************************************************************/
2029 {
2030  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2031 
2032  TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2033 
2034  if (ddraw->flags & DDRAW_INITIALIZED)
2035  return DDERR_ALREADYINITIALIZED;
2036 
2037  /* FIXME: To properly take the GUID into account we should call
2038  * ddraw_init() here instead of in DDRAW_Create(). */
2039  if (guid)
2040  FIXME("Ignoring guid %s.\n", debugstr_guid(guid));
2041 
2043  return DD_OK;
2044 }
2045 
2046 static HRESULT WINAPI ddraw4_Initialize(IDirectDraw4 *iface, GUID *guid)
2047 {
2048  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2049 
2050  TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2051 
2053 }
2054 
2055 static HRESULT WINAPI ddraw2_Initialize(IDirectDraw2 *iface, GUID *guid)
2056 {
2057  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2058 
2059  TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2060 
2062 }
2063 
2064 static HRESULT WINAPI ddraw1_Initialize(IDirectDraw *iface, GUID *guid)
2065 {
2066  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2067 
2068  TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2069 
2071 }
2072 
2073 static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID riid)
2074 {
2075  TRACE("iface %p, riid %s.\n", iface, debugstr_guid(riid));
2076 
2077  return DDERR_ALREADYINITIALIZED;
2078 }
2079 
2080 /*****************************************************************************
2081  * IDirectDraw7::FlipToGDISurface
2082  *
2083  * "Makes the surface that the GDI writes to the primary surface"
2084  * Looks like some windows specific thing we don't have to care about.
2085  * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to
2086  * show error boxes ;)
2087  * Well, just return DD_OK.
2088  *
2089  * Returns:
2090  * Always returns DD_OK
2091  *
2092  *****************************************************************************/
2094 {
2095  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2096 
2097  TRACE("iface %p.\n", iface);
2098 
2100 
2101  if (ddraw->primary)
2103 
2104  return DD_OK;
2105 }
2106 
2107 static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface)
2108 {
2109  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2110 
2111  TRACE("iface %p.\n", iface);
2112 
2114 }
2115 
2116 static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface)
2117 {
2118  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2119 
2120  TRACE("iface %p.\n", iface);
2121 
2123 }
2124 
2125 static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface)
2126 {
2127  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2128 
2129  TRACE("iface %p.\n", iface);
2130 
2132 }
2133 
2134 /*****************************************************************************
2135  * IDirectDraw7::WaitForVerticalBlank
2136  *
2137  * This method allows applications to get in sync with the vertical blank
2138  * interval.
2139  * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't
2140  * redraw the screen, most likely because of this stub
2141  *
2142  * Parameters:
2143  * Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT
2144  * or DDWAITVB_BLOCKEND
2145  * h: Not used, according to MSDN
2146  *
2147  * Returns:
2148  * Always returns DD_OK
2149  *
2150  *****************************************************************************/
2152 {
2153  static BOOL hide;
2154 
2155  TRACE("iface %p, flags %#x, event %p.\n", iface, Flags, event);
2156 
2157  /* This function is called often, so print the fixme only once */
2158  if(!hide)
2159  {
2160  FIXME("iface %p, flags %#x, event %p stub!\n", iface, Flags, event);
2161  hide = TRUE;
2162  }
2163 
2164  /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */
2166  return DDERR_UNSUPPORTED; /* unchecked */
2167 
2168  return DD_OK;
2169 }
2170 
2172 {
2173  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2174 
2175  TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2176 
2178 }
2179 
2181 {
2182  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2183 
2184  TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2185 
2187 }
2188 
2190 {
2191  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2192 
2193  TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2194 
2196 }
2197 
2199 {
2200  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2201  struct wined3d_raster_status raster_status;
2202  HRESULT hr;
2203 
2204  TRACE("iface %p, line %p.\n", iface, Scanline);
2205 
2209  if (FAILED(hr))
2210  {
2211  WARN("Failed to get raster status, hr %#x.\n", hr);
2212  return hr;
2213  }
2214 
2215  *Scanline = raster_status.scan_line;
2216 
2217  if (raster_status.in_vblank)
2219 
2220  return DD_OK;
2221 }
2222 
2223 static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line)
2224 {
2225  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2226 
2227  TRACE("iface %p, line %p.\n", iface, line);
2228 
2230 }
2231 
2232 static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line)
2233 {
2234  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2235 
2236  TRACE("iface %p, line %p.\n", iface, line);
2237 
2239 }
2240 
2241 static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line)
2242 {
2243  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2244 
2245  TRACE("iface %p, line %p.\n", iface, line);
2246 
2248 }
2249 
2251 {
2252  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2253 
2254  TRACE("iface %p.\n", iface);
2255 
2257 }
2258 
2259 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface)
2260 {
2261  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2262 
2263  TRACE("iface %p.\n", iface);
2264 
2266 }
2267 
2268 /*****************************************************************************
2269  * IDirectDraw7::GetGDISurface
2270  *
2271  * Returns the surface that GDI is treating as the primary surface.
2272  * For Wine this is the front buffer
2273  *
2274  * Params:
2275  * GDISurface: Address to write the surface pointer to
2276  *
2277  * Returns:
2278  * DD_OK if the surface was found
2279  * DDERR_NOTFOUND if the GDI surface wasn't found
2280  *
2281  *****************************************************************************/
2283 {
2284  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2285 
2286  TRACE("iface %p, surface %p.\n", iface, GDISurface);
2287 
2289 
2290  if (!(*GDISurface = &ddraw->primary->IDirectDrawSurface7_iface))
2291  {
2292  WARN("Primary not created yet.\n");
2294  return DDERR_NOTFOUND;
2295  }
2296  IDirectDrawSurface7_AddRef(*GDISurface);
2297 
2299 
2300  return DD_OK;
2301 }
2302 
2303 static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface)
2304 {
2305  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2306  struct ddraw_surface *surface_impl;
2307  IDirectDrawSurface7 *surface7;
2308  HRESULT hr;
2309 
2310  TRACE("iface %p, surface %p.\n", iface, surface);
2311 
2313  if (FAILED(hr))
2314  {
2315  *surface = NULL;
2316  return hr;
2317  }
2318  surface_impl = impl_from_IDirectDrawSurface7(surface7);
2319  *surface = &surface_impl->IDirectDrawSurface4_iface;
2320  IDirectDrawSurface4_AddRef(*surface);
2321  IDirectDrawSurface7_Release(surface7);
2322 
2323  return hr;
2324 }
2325 
2326 static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface)
2327 {
2328  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2329  struct ddraw_surface *surface_impl;
2330  IDirectDrawSurface7 *surface7;
2331  HRESULT hr;
2332 
2333  TRACE("iface %p, surface %p.\n", iface, surface);
2334 
2336  if (FAILED(hr))
2337  {
2338  *surface = NULL;
2339  return hr;
2340  }
2341  surface_impl = impl_from_IDirectDrawSurface7(surface7);
2342  *surface = &surface_impl->IDirectDrawSurface_iface;
2343  IDirectDrawSurface_AddRef(*surface);
2344  IDirectDrawSurface7_Release(surface7);
2345 
2346  return hr;
2347 }
2348 
2349 static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface)
2350 {
2351  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2352  struct ddraw_surface *surface_impl;
2353  IDirectDrawSurface7 *surface7;
2354  HRESULT hr;
2355 
2356  TRACE("iface %p, surface %p.\n", iface, surface);
2357 
2359  if (FAILED(hr))
2360  {
2361  *surface = NULL;
2362  return hr;
2363  }
2364  surface_impl = impl_from_IDirectDrawSurface7(surface7);
2365  *surface = &surface_impl->IDirectDrawSurface_iface;
2366  IDirectDrawSurface_AddRef(*surface);
2367  IDirectDrawSurface7_Release(surface7);
2368 
2369  return hr;
2370 }
2371 
2373 {
2375  void *context;
2376 };
2377 
2379 {
2380  struct displaymodescallback_context *cbcontext = context;
2382 
2383  DDSD2_to_DDSD(surface_desc, &desc);
2384  return cbcontext->func(&desc, cbcontext->context);
2385 }
2386 
2387 /*****************************************************************************
2388  * IDirectDraw7::EnumDisplayModes
2389  *
2390  * Enumerates the supported Display modes. The modes can be filtered with
2391  * the DDSD parameter.
2392  *
2393  * Params:
2394  * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES. For old ddraw
2395  * versions (3 and older?) this is reserved and must be 0.
2396  * DDSD: Surface description to filter the modes
2397  * Context: Pointer passed back to the callback function
2398  * cb: Application-provided callback function
2399  *
2400  * Returns:
2401  * DD_OK on success
2402  * DDERR_INVALIDPARAMS if the callback wasn't set
2403  *
2404  *****************************************************************************/
2407 {
2408  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2409  struct wined3d_display_mode *enum_modes = NULL;
2410  struct wined3d_display_mode mode;
2411  unsigned int modenum, fmt;
2412  DDSURFACEDESC2 callback_sd;
2413  unsigned enum_mode_count = 0, enum_mode_array_size = 16;
2415 
2416  static const enum wined3d_format_id checkFormatList[] =
2417  {
2421  };
2422 
2423  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2424  iface, Flags, DDSD, Context, cb);
2425 
2426  if (!cb)
2427  return DDERR_INVALIDPARAMS;
2428 
2429  if (!(enum_modes = heap_alloc(enum_mode_array_size * sizeof(*enum_modes))))
2430  return DDERR_OUTOFMEMORY;
2431 
2433 
2434  pixelformat.dwSize = sizeof(pixelformat);
2435  for(fmt = 0; fmt < ARRAY_SIZE(checkFormatList); fmt++)
2436  {
2437  modenum = 0;
2440  {
2441  BOOL found = FALSE;
2442  unsigned i;
2443 
2445  if (DDSD)
2446  {
2447  if (DDSD->dwFlags & DDSD_WIDTH && mode.width != DDSD->dwWidth)
2448  continue;
2449  if (DDSD->dwFlags & DDSD_HEIGHT && mode.height != DDSD->dwHeight)
2450  continue;
2451  if (DDSD->dwFlags & DDSD_REFRESHRATE && mode.refresh_rate != DDSD->u2.dwRefreshRate)
2452  continue;
2453  if (DDSD->dwFlags & DDSD_PIXELFORMAT
2454  && pixelformat.u1.dwRGBBitCount != DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount)
2455  continue;
2456  }
2457 
2458  /* DX docs state EnumDisplayMode should return only unique modes */
2459  for (i = 0; i < enum_mode_count; i++)
2460  {
2461  if (enum_modes[i].width == mode.width && enum_modes[i].height == mode.height
2462  && enum_modes[i].format_id == mode.format_id
2463  && (enum_modes[i].refresh_rate == mode.refresh_rate || !(Flags & DDEDM_REFRESHRATES)))
2464  {
2465  found = TRUE;
2466  break;
2467  }
2468  }
2469  if(found) continue;
2470 
2471  memset(&callback_sd, 0, sizeof(callback_sd));
2472  callback_sd.dwSize = sizeof(callback_sd);
2473  callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
2474 
2476  if (Flags & DDEDM_REFRESHRATES)
2477  callback_sd.u2.dwRefreshRate = mode.refresh_rate;
2478 
2479  callback_sd.dwWidth = mode.width;
2480  callback_sd.dwHeight = mode.height;
2481 
2482  callback_sd.u4.ddpfPixelFormat=pixelformat;
2483 
2484  /* Calc pitch and DWORD align like MSDN says */
2485  callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.width;
2486  callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3;
2487 
2488  TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
2489  callback_sd.u2.dwRefreshRate);
2490 
2491  if(cb(&callback_sd, Context) == DDENUMRET_CANCEL)
2492  {
2493  TRACE("Application asked to terminate the enumeration\n");
2494  heap_free(enum_modes);
2496  return DD_OK;
2497  }
2498 
2499  if (enum_mode_count == enum_mode_array_size)
2500  {
2501  struct wined3d_display_mode *new_enum_modes;
2502 
2503  enum_mode_array_size *= 2;
2504  if (!(new_enum_modes = heap_realloc(enum_modes, enum_mode_array_size * sizeof(*new_enum_modes))))
2505  {
2506  heap_free(enum_modes);
2508  return DDERR_OUTOFMEMORY;
2509  }
2510 
2511  enum_modes = new_enum_modes;
2512  }
2513  enum_modes[enum_mode_count++] = mode;
2514  }
2515  }
2516 
2517  TRACE("End of enumeration\n");
2518  heap_free(enum_modes);
2520 
2521  return DD_OK;
2522 }
2523 
2524 static HRESULT WINAPI ddraw4_EnumDisplayModes(IDirectDraw4 *iface, DWORD flags,
2525  DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMMODESCALLBACK2 callback)
2526 {
2527  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2528 
2529  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2530  iface, flags, surface_desc, context, callback);
2531 
2533 }
2534 
2535 static HRESULT WINAPI ddraw2_EnumDisplayModes(IDirectDraw2 *iface, DWORD flags,
2536  DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2537 {
2538  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2539  struct displaymodescallback_context cbcontext;
2540  DDSURFACEDESC2 surface_desc2;
2541 
2542  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2543  iface, flags, surface_desc, context, callback);
2544 
2545  cbcontext.func = callback;
2546  cbcontext.context = context;
2547 
2548  if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2550  surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2551 }
2552 
2553 static HRESULT WINAPI ddraw1_EnumDisplayModes(IDirectDraw *iface, DWORD flags,
2554  DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2555 {
2556  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2557  struct displaymodescallback_context cbcontext;
2558  DDSURFACEDESC2 surface_desc2;
2559 
2560  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2561  iface, flags, surface_desc, context, callback);
2562 
2563  cbcontext.func = callback;
2564  cbcontext.context = context;
2565 
2566  if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2568  surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2569 }
2570 
2571 /*****************************************************************************
2572  * IDirectDraw7::EvaluateMode
2573  *
2574  * Used with IDirectDraw7::StartModeTest to test video modes.
2575  * EvaluateMode is used to pass or fail a mode, and continue with the next
2576  * mode
2577  *
2578  * Params:
2579  * Flags: DDEM_MODEPASSED or DDEM_MODEFAILED
2580  * Timeout: Returns the amount of seconds left before the mode would have
2581  * been failed automatically
2582  *
2583  * Returns:
2584  * This implementation always DD_OK, because it's a stub
2585  *
2586  *****************************************************************************/
2588 {
2589  FIXME("iface %p, flags %#x, timeout %p stub!\n", iface, Flags, Timeout);
2590 
2591  /* When implementing this, implement it in WineD3D */
2592 
2593  return DD_OK;
2594 }
2595 
2596 /*****************************************************************************
2597  * IDirectDraw7::GetDeviceIdentifier
2598  *
2599  * Returns the device identifier, which gives information about the driver
2600  * Our device identifier is defined at the beginning of this file.
2601  *
2602  * Params:
2603  * DDDI: Address for the returned structure
2604  * Flags: Can be DDGDI_GETHOSTIDENTIFIER
2605  *
2606  * Returns:
2607  * On success it returns DD_OK
2608  * DDERR_INVALIDPARAMS if DDDI is NULL
2609  *
2610  *****************************************************************************/
2613 {
2614  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2615  struct wined3d_adapter_identifier adapter_id;
2616  HRESULT hr = S_OK;
2617 
2618  TRACE("iface %p, device_identifier %p, flags %#x.\n", iface, DDDI, Flags);
2619 
2620  if (!DDDI)
2621  return DDERR_INVALIDPARAMS;
2622 
2624  {
2625  /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D
2626  * host adapter, if there's a secondary 3D adapter. This doesn't apply
2627  * to any modern hardware, nor is it interesting for Wine, so ignore it.
2628  * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4
2629  * bytes too long. So only copy the relevant part of the structure
2630  */
2631 
2633  return DD_OK;
2634  }
2635 
2636  /* Drakan: Order of the Flame expects accurate D3D device information from ddraw */
2637  adapter_id.driver = DDDI->szDriver;
2638  adapter_id.driver_size = sizeof(DDDI->szDriver);
2639  adapter_id.description = DDDI->szDescription;
2640  adapter_id.description_size = sizeof(DDDI->szDescription);
2641  adapter_id.device_name_size = 0;
2645  if (FAILED(hr)) return hr;
2646 
2647  DDDI->liDriverVersion = adapter_id.driver_version;
2648  DDDI->dwVendorId = adapter_id.vendor_id;
2649  DDDI->dwDeviceId = adapter_id.device_id;
2650  DDDI->dwSubSysId = adapter_id.subsystem_id;
2651  DDDI->dwRevision = adapter_id.revision;
2652  DDDI->guidDeviceIdentifier = adapter_id.device_identifier;
2653  DDDI->dwWHQLLevel = adapter_id.whql_level;
2654  return DD_OK;
2655 }
2656 
2657 static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface,
2658  DDDEVICEIDENTIFIER *identifier, DWORD flags)
2659 {
2660  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2661  DDDEVICEIDENTIFIER2 identifier2;
2662  HRESULT hr;
2663 
2664  TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags);
2665 
2667  DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier);
2668 
2669  return hr;
2670 }
2671 
2672 /*****************************************************************************
2673  * IDirectDraw7::GetSurfaceFromDC
2674  *
2675  * Returns the Surface for a GDI device context handle.
2676  * Is this related to IDirectDrawSurface::GetDC ???
2677  *
2678  * Params:
2679  * hdc: hdc to return the surface for
2680  * Surface: Address to write the surface pointer to
2681  *
2682  * Returns:
2683  * Always returns DD_OK because it's a stub
2684  *
2685  *****************************************************************************/
2687  HDC dc, IDirectDrawSurface7 **surface)
2688 {
2689  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2690  struct ddraw_surface *surface_impl;
2691 
2692  TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2693 
2694  if (!surface)
2695  return E_INVALIDARG;
2696 
2697  if (!dc)
2698  goto done;
2699 
2702  {
2703  if (surface_impl->dc != dc)
2704  continue;
2705 
2706  TRACE("Found surface %p for dc %p.\n", surface_impl, dc);
2707  *surface = &surface_impl->IDirectDrawSurface7_iface;
2708  IDirectDrawSurface7_AddRef(*surface);
2710  return DD_OK;
2711  }
2713 
2714 done:
2715  TRACE("No surface found for dc %p.\n", dc);
2716  *surface = NULL;
2717  return DDERR_NOTFOUND;
2718 }
2719 
2720 static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc,
2721  IDirectDrawSurface4 **surface)
2722 {
2723  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2724  struct ddraw_surface *surface_impl;
2725  IDirectDrawSurface7 *surface7;
2726  HRESULT hr;
2727 
2728  TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2729 
2730  if (!surface) return E_INVALIDARG;
2731 
2733  if (FAILED(hr))
2734  {
2735  *surface = NULL;
2736  return hr;
2737  }
2738  surface_impl = impl_from_IDirectDrawSurface7(surface7);
2739  /* Tests say this is true */
2740  *surface = (IDirectDrawSurface4 *)&surface_impl->IDirectDrawSurface_iface;
2741  IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
2742  IDirectDrawSurface7_Release(surface7);
2743 
2744  return hr;
2745 }
2746 
2748 {
2749  IDirectDrawSurface_Restore(surface);
2750  IDirectDrawSurface_Release(surface);
2751 
2752  return DDENUMRET_OK;
2753 }
2754 
2756 {
2757  TRACE("iface %p.\n", iface);
2758 
2759  return IDirectDraw7_EnumSurfaces(iface, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
2761 }
2762 
2763 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
2764 {
2765  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2766 
2767  TRACE("iface %p.\n", iface);
2768 
2770 }
2771 
2772 /*****************************************************************************
2773  * IDirectDraw7::StartModeTest
2774  *
2775  * Tests the specified video modes to update the system registry with
2776  * refresh rate information. StartModeTest starts the mode test,
2777  * EvaluateMode is used to fail or pass a mode. If EvaluateMode
2778  * isn't called within 15 seconds, the mode is failed automatically
2779  *
2780  * As refresh rates are handled by the X server, I don't think this
2781  * Method is important
2782  *
2783  * Params:
2784  * Modes: An array of mode specifications
2785  * NumModes: The number of modes in Modes
2786  * Flags: Some flags...
2787  *
2788  * Returns:
2789  * Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
2790  * if no modes are passed, DDERR_INVALIDPARAMS is returned,
2791  * otherwise DD_OK
2792  *
2793  *****************************************************************************/
2795 {
2796  FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n",
2797  iface, Modes, NumModes, Flags);
2798 
2799  /* This looks sane */
2800  if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
2801 
2802  /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
2803  * As it is not, DDERR_TESTFINISHED is returned
2804  * (hopefully that's correct
2805  *
2806  if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
2807  * well, that value doesn't (yet) exist in the wine headers, so ignore it
2808  */
2809 
2810  return DD_OK;
2811 }
2812 
2814  IDirectDrawSurface7 **surface, IUnknown *outer_unknown)
2815 {
2816  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2817  struct ddraw_surface *impl;
2818  HRESULT hr;
2819 
2820  TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2821  iface, surface_desc, surface, outer_unknown);
2822 
2824 
2826  {
2827  WARN("Cooperative level not set.\n");
2830  }
2831 
2832  if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2833  {
2834  WARN("Application supplied invalid surface descriptor\n");
2836  return DDERR_INVALIDPARAMS;
2837  }
2838 
2839  __TRY
2840  {
2841  *surface = NULL;
2842  }
2844  {
2845  WARN("Surface pointer %p is invalid.\n", surface);
2847  return DDERR_INVALIDPARAMS;
2848  }
2849  __ENDTRY;
2850 
2852  {
2853  if (TRACE_ON(ddraw))
2854  {
2855  TRACE(" (%p) Requesting surface desc :\n", iface);
2857  }
2858 
2859  WARN("Application tried to create an explicit front or back buffer\n");
2861  return DDERR_INVALIDCAPS;
2862  }
2863 
2864  hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 7);
2866  if (FAILED(hr))
2867  return hr;
2868 
2869  *surface = &impl->IDirectDrawSurface7_iface;
2870  IDirectDraw7_AddRef(iface);
2871  impl->ifaceToRelease = (IUnknown *)iface;
2872 
2873  return hr;
2874 }
2875 
2876 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
2877  DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown)
2878 {
2879  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2880  struct ddraw_surface *impl;
2881  HRESULT hr;
2882 
2883  TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2884  iface, surface_desc, surface, outer_unknown);
2885 
2887 
2889  {
2890  WARN("Cooperative level not set.\n");
2893  }
2894 
2895  if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2896  {
2897  WARN("Application supplied invalid surface descriptor\n");
2899  return DDERR_INVALIDPARAMS;
2900  }
2901 
2902  __TRY
2903  {
2904  *surface = NULL;
2905  }
2907  {
2908  WARN("Surface pointer %p is invalid.\n", surface);
2910  return DDERR_INVALIDPARAMS;
2911  }
2912  __ENDTRY;
2913 
2915  {
2916  if (TRACE_ON(ddraw))
2917  {
2918  TRACE(" (%p) Requesting surface desc :\n", iface);
2920  }
2921 
2922  WARN("Application tried to create an explicit front or back buffer\n");
2924  return DDERR_INVALIDCAPS;
2925  }
2926 
2927  hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 4);
2929  if (FAILED(hr))
2930  return hr;
2931 
2932  *surface = &impl->IDirectDrawSurface4_iface;
2933  IDirectDraw4_AddRef(iface);
2934  impl->ifaceToRelease = (IUnknown *)iface;
2935 
2936  return hr;
2937 }
2938 
2939 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
2940  DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
2941 {
2942  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2943  struct ddraw_surface *impl;
2944  HRESULT hr;
2945  DDSURFACEDESC2 surface_desc2;
2946 
2947  TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2948  iface, surface_desc, surface, outer_unknown);
2949 
2951 
2953  {
2954  WARN("Cooperative level not set.\n");
2957  }
2958 
2959  if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
2960  {
2961  WARN("Application supplied invalid surface descriptor\n");
2963  return DDERR_INVALIDPARAMS;
2964  }
2965 
2966  __TRY
2967  {
2968  *surface = NULL;
2969  }
2971  {
2972  WARN("Surface pointer %p is invalid.\n", surface);
2974  return DDERR_INVALIDPARAMS;
2975  }
2976  __ENDTRY;
2977 
2978  DDSD_to_DDSD2(surface_desc, &surface_desc2);
2980  {
2981  if (TRACE_ON(ddraw))
2982  {
2983  TRACE(" (%p) Requesting surface desc :\n", iface);
2985  }
2986 
2987  WARN("Application tried to create an explicit front or back buffer\n");
2989  return DDERR_INVALIDCAPS;
2990  }
2991 
2992  hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 2);
2994  if (FAILED(hr))
2995  return hr;
2996 
2997  *surface = &impl->IDirectDrawSurface_iface;
2998  impl->ifaceToRelease = NULL;
2999 
3000  return hr;
3001 }
3002 
3003 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
3004  DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3005 {
3006  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3007  struct ddraw_surface *impl;
3008  HRESULT hr;
3009  DDSURFACEDESC2 surface_desc2;
3010 
3011  TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3012  iface, surface_desc, surface, outer_unknown);
3013 
3015 
3017  {
3018  WARN("Cooperative level not set.\n");
3021  }
3022 
3023  if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3024  {
3025  WARN("Application supplied invalid surface descriptor\n");
3027  return DDERR_INVALIDPARAMS;
3028  }
3029 
3030  __TRY
3031  {
3032  *surface = NULL;
3033  }
3035  {
3036  WARN("Surface pointer %p is invalid.\n", surface);
3038  return DDERR_INVALIDPARAMS;
3039  }
3040  __ENDTRY;
3041 
3046  {
3047  WARN("Application tried to create an explicit front or back buffer.\n");
3049  return DDERR_INVALIDCAPS;
3050  }
3051 
3052  DDSD_to_DDSD2(surface_desc, &surface_desc2);
3053  hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 1);
3055  if (FAILED(hr))
3056  return hr;
3057 
3058  *surface = &impl->IDirectDrawSurface_iface;
3059  impl->ifaceToRelease = NULL;
3060 
3061  return hr;
3062 }
3063 
3064 static BOOL
3066  const DDPIXELFORMAT *provided)
3067 {
3068  /* Some flags must be present in both or neither for a match. */
3069  static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
3072 
3073  if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3074  return FALSE;
3075 
3076  if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
3077  return FALSE;
3078 
3079  if (requested->dwFlags & DDPF_FOURCC)
3080  if (requested->dwFourCC != provided->dwFourCC)
3081  return FALSE;
3082 
3083  if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA
3085  if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount)
3086  return FALSE;
3087 
3088  if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3090  if (requested->u2.dwRBitMask != provided->u2.dwRBitMask)
3091  return FALSE;
3092 
3093  if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV))
3094  if (requested->u3.dwGBitMask != provided->u3.dwGBitMask)
3095  return FALSE;
3096 
3097  /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3098  if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3099  |DDPF_BUMPDUDV))
3100  if (requested->u4.dwBBitMask != provided->u4.dwBBitMask)
3101  return FALSE;
3102 
3103  if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
3104  if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask)
3105  return FALSE;
3106 
3107  return TRUE;
3108 }
3109 
3110 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided)
3111 {
3112  struct compare_info
3113  {
3114  DWORD flag;
3115  ptrdiff_t offset;
3116  size_t size;
3117  };
3118 
3119 #define CMP(FLAG, FIELD) \
3120  { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3121  sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3122 
3123  static const struct compare_info compare[] =
3124  {
3125  CMP(ALPHABITDEPTH, dwAlphaBitDepth),
3126  CMP(BACKBUFFERCOUNT, u5.dwBackBufferCount),
3127  CMP(CAPS, ddsCaps),
3128  CMP(CKDESTBLT, ddckCKDestBlt),
3129  CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */),
3130  CMP(CKSRCBLT, ddckCKSrcBlt),
3131  CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
3132  CMP(HEIGHT, dwHeight),
3133  CMP(LINEARSIZE, u1 /* dwLinearSize */),
3134  CMP(LPSURFACE, lpSurface),
3135  CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */),
3136  CMP(PITCH, u1 /* lPitch */),
3137  /* PIXELFORMAT: manual */
3138  CMP(REFRESHRATE, u2 /* dwRefreshRate */),
3139  CMP(TEXTURESTAGE, dwTextureStage),
3140  CMP(WIDTH, dwWidth),
3141  /* ZBUFFERBITDEPTH: "obsolete" */
3142  };
3143 
3144 #undef CMP
3145 
3146  unsigned int i;
3147 
3148  if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3149  return FALSE;
3150 
3151  for (i=0; i < ARRAY_SIZE(compare); i++)
3152  {
3153  if (requested->dwFlags & compare[i].flag
3154  && memcmp((const char *)provided + compare[i].offset,
3155  (const char *)requested + compare[i].offset,
3156  compare[i].size) != 0)
3157  return FALSE;
3158  }
3159 
3160  if (requested->dwFlags & DDSD_PIXELFORMAT)
3161  {
3163  &provided->u4.ddpfPixelFormat))
3164  return FALSE;
3165  }
3166 
3167  return TRUE;
3168 }
3169 
3171 {
3173  void *context;
3174 };
3175 
3177 {
3179  void *context;
3180 };
3181 
3183  DDSURFACEDESC2 *surface_desc, void *context)
3184 {
3185  struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3186  struct surfacescallback2_context *cbcontext = context;
3187 
3188  IDirectDrawSurface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
3189  IDirectDrawSurface7_Release(surface);
3190 
3191  return cbcontext->func(&surface_impl->IDirectDrawSurface4_iface,
3192  surface_desc, cbcontext->context);
3193 }
3194 
3196  DDSURFACEDESC2 *surface_desc, void *context)
3197 {
3198  struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3199  struct surfacescallback_context *cbcontext = context;
3200 
3201  IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
3202  IDirectDrawSurface7_Release(surface);
3203 
3204  return cbcontext->func(&surface_impl->IDirectDrawSurface_iface,
3205  (DDSURFACEDESC *)surface_desc, cbcontext->context);
3206 }
3207 
3208 /*****************************************************************************
3209  * IDirectDraw7::EnumSurfaces
3210  *
3211  * Loops through all surfaces attached to this device and calls the
3212  * application callback. This can't be relayed to WineD3DDevice,
3213  * because some WineD3DSurfaces' parents are IParent objects
3214  *
3215  * Params:
3216  * Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3217  * DDSD: Description to filter for
3218  * Context: Application-provided pointer, it's passed unmodified to the
3219  * Callback function
3220  * Callback: Address to call for each surface
3221  *
3222  * Returns:
3223  * DDERR_INVALIDPARAMS if the callback is NULL
3224  * DD_OK on success
3225  *
3226  *****************************************************************************/
3229 {
3230  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3231  struct ddraw_surface *surf;
3233 
3234  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3235  iface, Flags, DDSD, Context, Callback);
3236 
3237  if (!Callback)
3238  return DDERR_INVALIDPARAMS;
3239 
3241  {
3242  IDirectDrawSurface7 *surface;
3243  DDSURFACEDESC2 testdesc;
3244  HRESULT hr;
3245 
3246  if (match_flags != DDENUMSURFACES_MATCH)
3247  return DDERR_INVALIDPARAMS;
3248 
3249  if (!DDSD)
3250  return DDERR_INVALIDPARAMS;
3251 
3252  memcpy(&testdesc, DDSD, sizeof(testdesc));
3253  if (!(testdesc.dwFlags & DDSD_WIDTH))
3254  {
3255  testdesc.dwFlags |= DDSD_WIDTH;
3256  testdesc.dwWidth = 512;
3257  }
3258  if (!(testdesc.dwFlags & DDSD_HEIGHT))
3259  {
3260  testdesc.dwFlags |= DDSD_HEIGHT;
3261  testdesc.dwHeight = 512;
3262  }
3263 
3264  hr = IDirectDraw7_CreateSurface(iface, &testdesc, &surface, NULL);
3265  if (SUCCEEDED(hr))
3266  {
3267  surf = unsafe_impl_from_IDirectDrawSurface7(surface);
3268  Callback(NULL, &surf->surface_desc, Context);
3269  IDirectDrawSurface7_Release(surface);
3270  }
3271  else
3272  ERR("Failed to create surface, hr %#x.\n", hr);
3273  }
3274  else if (Flags & DDENUMSURFACES_DOESEXIST)
3275  {
3276  BOOL all, nomatch;
3278  struct list *entry, *entry2;
3279 
3280  /* a combination of match flags is not allowed */
3281  if (match_flags != 0 &&
3282  match_flags != DDENUMSURFACES_ALL &&
3283  match_flags != DDENUMSURFACES_MATCH &&
3284  match_flags != DDENUMSURFACES_NOMATCH)
3285  return DDERR_INVALIDPARAMS;
3286 
3287  all = (Flags & DDENUMSURFACES_ALL) != 0;
3288  nomatch = (Flags & DDENUMSURFACES_NOMATCH) != 0;
3289 
3290  if (!all && !DDSD)
3291  return DDERR_INVALIDPARAMS;
3292 
3294 
3295  /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
3297  {
3298  surf = LIST_ENTRY(entry, struct ddraw_surface, surface_list_entry);
3299 
3300  if (!surf->iface_count)
3301  {
3302  WARN("Not enumerating surface %p because it doesn't have any references.\n", surf);
3303  continue;
3304  }
3305 
3306  if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc)))
3307  {
3308  TRACE("Enumerating surface %p.\n", surf);
3309  desc = surf->surface_desc;
3310  IDirectDrawSurface7_AddRef(&surf->IDirectDrawSurface7_iface);
3312  {
3314  return DD_OK;
3315  }
3316  }
3317  }
3318 
3320  }
3321  else
3322  return DDERR_INVALIDPARAMS;
3323 
3324  return DD_OK;
3325 }
3326 
3327 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags,
3329 {
3330  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3331  struct surfacescallback2_context cbcontext;
3332 
3333  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3334  iface, flags, surface_desc, context, callback);
3335 
3336  cbcontext.func = callback;
3337  cbcontext.context = context;
3338 
3339  return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, surface_desc,
3340  &cbcontext, EnumSurfacesCallback2Thunk);
3341 }
3342 
3343 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags,
3345 {
3346  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3347  struct surfacescallback_context cbcontext;
3348  DDSURFACEDESC2 surface_desc2;
3349 
3350  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3351  iface, flags, surface_desc, context, callback);
3352 
3353  cbcontext.func = callback;
3354  cbcontext.context = context;
3355 
3356  if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3358  surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3359 }
3360 
3361 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags,
3363 {
3364  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3365  struct surfacescallback_context cbcontext;
3366  DDSURFACEDESC2 surface_desc2;
3367 
3368  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3369  iface, flags, surface_desc, context, callback);
3370 
3371  cbcontext.func = callback;
3372  cbcontext.context = context;
3373 
3374  if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3376  surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3377 }
3378 
3379 /*****************************************************************************
3380  * DirectDrawCreateClipper (DDRAW.@)
3381  *
3382  * Creates a new IDirectDrawClipper object.
3383  *
3384  * Params:
3385  * Clipper: Address to write the interface pointer to
3386  * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3387  * NULL
3388  *
3389  * Returns:
3390  * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3391  * E_OUTOFMEMORY if allocating the object failed
3392  *
3393  *****************************************************************************/
3394 HRESULT WINAPI DirectDrawCreateClipper(DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3395 {
3396  struct ddraw_clipper *object;
3397  HRESULT hr;
3398 
3399  TRACE("flags %#x, clipper %p, outer_unknown %p.\n",
3400  flags, clipper, outer_unknown);
3401 
3402  if (outer_unknown)
3403  return CLASS_E_NOAGGREGATION;
3404 
3406 
3407  if (!(object = heap_alloc_zero(sizeof(*object))))
3408  {
3410  return E_OUTOFMEMORY;
3411  }
3412 
3413  hr = ddraw_clipper_init(object);
3414  if (FAILED(hr))
3415  {
3416  WARN("Failed to initialize clipper, hr %#x.\n", hr);
3417  heap_free(object);
3419  return hr;
3420  }
3421 
3422  TRACE("Created clipper %p.\n", object);
3423  *clipper = &object->IDirectDrawClipper_iface;
3425 
3426  return DD_OK;
3427 }
3428 
3429 /*****************************************************************************
3430  * IDirectDraw7::CreateClipper
3431  *
3432  * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3433  *
3434  *****************************************************************************/
3436  IDirectDrawClipper **Clipper, IUnknown *UnkOuter)
3437 {
3438  TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3439  iface, Flags, Clipper, UnkOuter);
3440 
3441  return DirectDrawCreateClipper(Flags, Clipper, UnkOuter);
3442 }
3443 
3444 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface, DWORD flags,
3445  IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3446 {
3447  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3448 
3449  TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3450  iface, flags, clipper, outer_unknown);
3451 
3452  return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3453 }
3454 
3455 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface,
3456  DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3457 {
3458  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3459 
3460  TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3461  iface, flags, clipper, outer_unknown);
3462 
3463  return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3464 }
3465 
3466 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface,
3467  DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3468 {
3469  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3470 
3471  TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3472  iface, flags, clipper, outer_unknown);
3473 
3474  return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3475 }
3476 
3477 /*****************************************************************************
3478  * IDirectDraw7::CreatePalette
3479  *
3480  * Creates a new IDirectDrawPalette object
3481  *
3482  * Params:
3483  * Flags: The flags for the new clipper
3484  * ColorTable: Color table to assign to the new clipper
3485  * Palette: Address to write the interface pointer to
3486  * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3487  * NULL
3488  *
3489  * Returns:
3490  * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3491  * E_OUTOFMEMORY if allocating the object failed
3492  *
3493  *****************************************************************************/
3495  PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter)
3496 {
3497  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3498  struct ddraw_palette *object;
3499  HRESULT hr;
3500 
3501  TRACE("iface %p, flags %#x, color_table %p, palette %p, outer_unknown %p.\n",
3502  iface, Flags, ColorTable, Palette, pUnkOuter);
3503 
3504  if (pUnkOuter)
3505  return CLASS_E_NOAGGREGATION;
3506 
3508 
3509  /* The refcount test shows that a cooplevel is required for this */
3510  if (!ddraw->cooperative_level)
3511  {
3512  WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
3515  }
3516 
3517  if (!(object = heap_alloc(sizeof(*object))))
3518  {
3519  ERR("Out of memory when allocating memory for a palette implementation\n");
3521  return E_OUTOFMEMORY;
3522  }
3523 
3524  hr = ddraw_palette_init(object, ddraw, Flags, ColorTable);
3525  if (FAILED(hr))
3526  {
3527  WARN("Failed to initialize palette, hr %#x.\n", hr);
3528  heap_free(object);
3530  return hr;
3531  }
3532 
3533  TRACE("Created palette %p.\n", object);
3534  *Palette = &object->IDirectDrawPalette_iface;
3536 
3537  return DD_OK;
3538 }
3539 
3540 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags, PALETTEENTRY *entries,
3541  IDirectDrawPalette **palette, IUnknown *outer_unknown)
3542 {
3543  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3544  HRESULT hr;
3545 
3546  TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3547  iface, flags, entries, palette, outer_unknown);
3548 
3549  hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3550  if (SUCCEEDED(hr) && *palette)
3551  {
3553  IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3554  IDirectDraw4_AddRef(iface);
3555  impl->ifaceToRelease = (IUnknown *)iface;
3556  }
3557  return hr;
3558 }
3559 
3560 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags,
3561  PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3562 {
3563  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3564  HRESULT hr;
3565 
3566  TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3567  iface, flags, entries, palette, outer_unknown);
3568 
3569  hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3570  if (SUCCEEDED(hr) && *palette)
3571  {
3573  IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3574  impl->ifaceToRelease = NULL;
3575  }
3576 
3577  return hr;
3578 }
3579 
3580 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags,
3581  PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3582 {
3583  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3584  HRESULT hr;
3585 
3586  TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3587  iface, flags, entries, palette, outer_unknown);
3588 
3589  hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3590  if (SUCCEEDED(hr) && *palette)
3591  {
3593  IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3594  impl->ifaceToRelease = NULL;
3595  }
3596 
3597  return hr;
3598 }
3599 
3600 /*****************************************************************************
3601  * IDirectDraw7::DuplicateSurface
3602  *
3603  * Duplicates a surface. The surface memory points to the same memory as
3604  * the original surface, and it's released when the last surface referencing
3605  * it is released. I guess that's beyond Wine's surface management right now
3606  * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
3607  * test application to implement this)
3608  *
3609  * Params:
3610  * Src: Address of the source surface
3611  * Dest: Address to write the new surface pointer to
3612  *
3613  * Returns:
3614  * See IDirectDraw7::CreateSurface
3615  *
3616  *****************************************************************************/
3619 {
3620  struct ddraw_surface *src_surface = unsafe_impl_from_IDirectDrawSurface7(Src);
3621 
3622  FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest);
3623 
3624  /* For now, simply create a new, independent surface */
3625  return IDirectDraw7_CreateSurface(iface, &src_surface->surface_desc, Dest, NULL);
3626 }
3627 
3628 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSurface4 *src,
3629  IDirectDrawSurface4 **dst)
3630 {
3632  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3633  struct ddraw_surface *dst_impl;
3634  IDirectDrawSurface7 *dst7;
3635  HRESULT hr;
3636 
3637  TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3638 
3640  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3641  if (FAILED(hr))
3642  {
3643  *dst = NULL;
3644  return hr;
3645  }
3646  dst_impl = impl_from_IDirectDrawSurface7(dst7);
3647  *dst = &dst_impl->IDirectDrawSurface4_iface;
3648  IDirectDrawSurface4_AddRef(*dst);
3649  IDirectDrawSurface7_Release(dst7);
3650 
3651  return hr;
3652 }
3653 
3654 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface,
3655  IDirectDrawSurface *src, IDirectDrawSurface **dst)
3656 {
3658  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3659  struct ddraw_surface *dst_impl;
3660  IDirectDrawSurface7 *dst7;
3661  HRESULT hr;
3662 
3663  TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3664 
3666  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3667  if (FAILED(hr))
3668  return hr;
3669  dst_impl = impl_from_IDirectDrawSurface7(dst7);
3670  *dst = &dst_impl->IDirectDrawSurface_iface;
3671  IDirectDrawSurface_AddRef(*dst);
3672  IDirectDrawSurface7_Release(dst7);
3673 
3674  return hr;
3675 }
3676 
3677 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src,
3678  IDirectDrawSurface **dst)
3679 {
3681  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3682  struct ddraw_surface *dst_impl;
3683  IDirectDrawSurface7 *dst7;
3684  HRESULT hr;
3685 
3686  TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3687 
3689  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3690  if (FAILED(hr))
3691  return hr;
3692  dst_impl = impl_from_IDirectDrawSurface7(dst7);
3693  *dst = &dst_impl->IDirectDrawSurface_iface;
3694  IDirectDrawSurface_AddRef(*dst);
3695  IDirectDrawSurface7_Release(dst7);
3696 
3697  return hr;
3698 }
3699 
3700 /*****************************************************************************
3701  * IDirect3D7::EnumDevices
3702  *
3703  * The EnumDevices method for IDirect3D7. It enumerates all supported
3704  * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated.
3705  *
3706  * Params:
3707  * callback: Function to call for each enumerated device
3708  * context: Pointer to pass back to the app
3709  *
3710  * Returns:
3711  * D3D_OK, or the return value of the GetCaps call
3712  *
3713  *****************************************************************************/
3715 {
3716  struct ddraw *ddraw = impl_from_IDirect3D7(iface);
3717  D3DDEVICEDESC7 device_desc7;
3718  DWORD dev_caps;
3719  HRESULT hr;
3720  size_t i;
3721 
3722  TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3723 
3724  if (!callback)
3725  return DDERR_INVALIDPARAMS;
3726 
3728 
3729  if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
3730  {
3732  return hr;
3733  }
3734 
3735  dev_caps = device_desc7.dwDevCaps;
3736 
3737  for (i = 0; i < ARRAY_SIZE(device_list7); i++)
3738  {
3739  HRESULT ret;
3740 
3741  device_desc7.deviceGUID = *device_list7[i].device_guid;
3742  device_desc7.dwDevCaps = dev_caps & ~device_list7[i].remove_caps;
3743 
3744  ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context);
3745  if (ret != DDENUMRET_OK)
3746  {
3747  TRACE("Application cancelled the enumeration.\n");
3749  return D3D_OK;
3750  }
3751  }
3752 
3753  TRACE("End of enumeration.\n");
3754 
3756 
3757  return D3D_OK;
3758 }
3759 
3760 /*****************************************************************************
3761  * IDirect3D3::EnumDevices
3762  *
3763  * Enumerates all supported Direct3DDevice interfaces. This is the
3764  * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
3765  *
3766  * Versions 1, 2 and 3
3767  *
3768  * Params:
3769  * callback: Application-provided routine to call for each enumerated device
3770  * Context: Pointer to pass to the callback
3771  *
3772  * Returns:
3773  * D3D_OK on success,
3774  * The result of IDirect3DImpl_GetCaps if it failed
3775  *
3776  *****************************************************************************/
3778 {
3779  static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
3780 
3781  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3782  D3DDEVICEDESC device_desc1, hal_desc, hel_desc;
3783  D3DDEVICEDESC7 device_desc7;
3784  HRESULT hr;
3785 
3786  /* Some games (Motoracer 2 demo) have the bad idea to modify the device
3787  * name string. Let's put the string in a sufficiently sized array in
3788  * writable memory. */
3789  char device_name[50];
3790  strcpy(device_name,"Direct3D HEL");
3791 
3792  TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3793 
3794  if (!callback)
3795  return DDERR_INVALIDPARAMS;
3796 
3798 
3799  if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
3800  {
3802  return hr;
3803  }
3804  ddraw_d3dcaps1_from_7(&device_desc1, &device_desc7);
3805 
3806  /* Do I have to enumerate the reference id? Note from old d3d7:
3807  * "It seems that enumerating the reference IID on Direct3D 1 games
3808  * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
3809  *
3810  * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers,
3811  * EnumReference which enables / disables enumerating the reference
3812  * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The
3813  * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk
3814  * demo directory suggest this.
3815  *
3816  * Some games(GTA 2) seem to use the second enumerated device, so I have
3817  * to enumerate at least 2 devices. So enumerate the reference device to
3818  * have 2 devices.
3819  *
3820  * Other games (Rollcage) tell emulation and hal device apart by certain
3821  * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a
3822  * limitation flag), and it refuses all devices that have the perspective
3823  * flag set. This way it refuses the emulation device, and HAL devices
3824  * never have POW2 unset in d3d7 on windows. */
3825  if (ddraw->d3dversion != 1)
3826  {
3827  static CHAR reference_description[] = "RGB Direct3D emulation";
3828 
3829  TRACE("Enumerating WineD3D D3DDevice interface.\n");
3830  hal_desc = device_desc1;
3831  hel_desc = device_desc1;
3832  /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */
3837  /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */
3838  hal_desc.dcmColorModel = 0;
3839  /* RGB, RAMP and MMX devices cannot report HAL hardware flags */
3840  hal_desc.dwFlags = 0;
3841 
3842  hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
3843  device_name, &hal_desc, &hel_desc, context);
3844  if (hr != D3DENUMRET_OK)
3845  {
3846  TRACE("Application cancelled the enumeration.\n");
3848  return D3D_OK;
3849  }
3850  }
3851 
3852  strcpy(device_name,"Direct3D HAL");
3853 
3854  TRACE("Enumerating HAL Direct3D device.\n");
3855  hal_desc = device_desc1;
3856  hel_desc = device_desc1;
3857 
3858  /* The hal device does not have the pow2 flag set in hel, but in hal. */
3863  /* HAL devices have a HEL dcmColorModel of 0 */
3864  hel_desc.dcmColorModel = 0;
3865 
3866  hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description,
3867  device_name, &hal_desc, &hel_desc, context);
3868  if (hr != D3DENUMRET_OK)
3869  {
3870  TRACE("Application cancelled the enumeration.\n");
3872  return D3D_OK;
3873  }
3874 
3875  TRACE("End of enumeration.\n");
3876 
3878 
3879  return D3D_OK;
3880 }
3881 
3883 {
3884  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3885 
3886  TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3887 
3889 }
3890 
3892 {
3893  struct ddraw *ddraw = impl_from_IDirect3D(iface);
3894 
3895  TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3896 
3898 }
3899 
3900 /*****************************************************************************
3901  * IDirect3D3::CreateLight
3902  *
3903  * Creates an IDirect3DLight interface. This interface is used in
3904  * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
3905  * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
3906  * uses the IDirect3DDevice7 interface with D3D7 lights.
3907  *
3908  * Versions 1, 2 and 3
3909  *
3910  * Params:
3911  * light: Address to store the new interface pointer
3912  * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3913  * Must be NULL
3914  *
3915  * Returns:
3916  * D3D_OK on success
3917  * DDERR_OUTOFMEMORY if memory allocation failed
3918  * CLASS_E_NOAGGREGATION if outer_unknown != NULL
3919  *
3920  *****************************************************************************/
3921 static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light,
3922  IUnknown *outer_unknown)
3923 {
3924  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3925  struct d3d_light *object;
3926 
3927  TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3928 
3929  if (outer_unknown)
3930  return CLASS_E_NOAGGREGATION;
3931 
3932  if (!(object = heap_alloc_zero(sizeof(*object))))
3933  {
3934  ERR("Failed to allocate light memory.\n");
3935  return DDERR_OUTOFMEMORY;
3936  }
3937 
3938  d3d_light_init(object, ddraw);
3939 
3940  TRACE("Created light %p.\n", object);
3941  *light = &object->IDirect3DLight_iface;
3942 
3943  return D3D_OK;
3944 }
3945 
3946 static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3947 {
3948  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3949 
3950  TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3951 
3952  return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
3953 }
3954 
3955 static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3956 {
3957  struct ddraw *ddraw = impl_from_IDirect3D(iface);
3958 
3959  TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3960 
3961  return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
3962 }
3963 
3964 /*****************************************************************************
3965  * IDirect3D3::CreateMaterial
3966  *
3967  * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
3968  * and older versions. The IDirect3DMaterial implementation wraps its
3969  * functionality to IDirect3DDevice7::SetMaterial and friends.
3970  *
3971  * Versions 1, 2 and 3
3972  *
3973  * Params:
3974  * material: Address to store the new interface's pointer to
3975  * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3976  * Must be NULL
3977  *
3978  * Returns:
3979  * D3D_OK on success
3980  * DDERR_OUTOFMEMORY if memory allocation failed
3981  * CLASS_E_NOAGGREGATION if outer_unknown != NULL
3982  *
3983  *****************************************************************************/
3984 static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material,
3985  IUnknown *outer_unknown)
3986 {
3987  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3988  struct d3d_material *object;
3989 
3990  TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
3991 
3992  if (outer_unknown) return CLASS_E_NOAGGREGATION;
3993 
3994  object = d3d_material_create(ddraw);
3995  if (!object)
3996  {
3997  ERR("Failed to allocate material memory.\n");
3998  return DDERR_OUTOFMEMORY;
3999  }
4000 
4001  TRACE("Created material %p.\n", object);
4002  *material = &object->IDirect3DMaterial3_iface;
4003 
4004  return D3D_OK;
4005 }
4006 
4007 static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material,
4008  IUnknown *outer_unknown)
4009 {
4010  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4011  struct d3d_material *object;
4012 
4013  TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4014 
4015  object = d3d_material_create(ddraw);
4016  if (!object)
4017  {
4018  ERR("Failed to allocate material memory.\n");
4019  return DDERR_OUTOFMEMORY;
4020  }
4021 
4022  TRACE("Created material %p.\n", object);
4023  *material = &object->IDirect3DMaterial2_iface;
4024 
4025  return D3D_OK;
4026 }
4027 
4028 static HRESULT WINAPI d3d1_CreateMaterial(IDirect3D *iface, IDirect3DMaterial **material,
4029  IUnknown *outer_unknown)
4030 {
4031  struct ddraw *ddraw = impl_from_IDirect3D(iface);
4032  struct d3d_material *object;
4033 
4034  TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4035 
4036  object = d3d_material_create(ddraw);
4037  if (!object)
4038  {
4039  ERR("Failed to allocate material memory.\n");
4040  return DDERR_OUTOFMEMORY;
4041  }
4042 
4043  TRACE("Created material %p.\n", object);
4044  *material = &object->IDirect3DMaterial_iface;
4045 
4046  return D3D_OK;
4047 }
4048 
4049 /*****************************************************************************
4050  * IDirect3D3::CreateViewport
4051  *
4052  * Creates an IDirect3DViewport interface. This interface is used
4053  * by Direct3D and earlier versions for Viewport management. In Direct3D7
4054  * it has been replaced by a viewport structure and
4055  * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation
4056  * uses the IDirect3DDevice7 methods for its functionality
4057  *
4058  * Params:
4059  * Viewport: Address to store the new interface pointer
4060  * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4061  * Must be NULL
4062  *
4063  * Returns:
4064  * D3D_OK on success
4065  * DDERR_OUTOFMEMORY if memory allocation failed
4066  * CLASS_E_NOAGGREGATION if outer_unknown != NULL
4067  *
4068  *****************************************************************************/
4069 static HRESULT WINAPI d3d3_CreateViewport(IDirect3D3 *iface, IDirect3DViewport3 **viewport,
4070  IUnknown *outer_unknown)
4071 {
4072  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4073  struct d3d_viewport *object;
4074 
4075  TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4076 
4077  if (outer_unknown) return CLASS_E_NOAGGREGATION;
4078 
4079  if (!(object = heap_alloc_zero(sizeof(*object))))
4080  {
4081  ERR("Failed to allocate viewport memory.\n");
4082  return DDERR_OUTOFMEMORY;
4083  }
4084 
4085  d3d_viewport_init(object, ddraw);
4086 
4087  TRACE("Created viewport %p.\n", object);
4088  *viewport = &object->IDirect3DViewport3_iface;
4089 
4090  return D3D_OK;
4091 }
4092 
4093 static HRESULT WINAPI d3d2_CreateViewport(IDirect3D2 *iface, IDirect3DViewport2 **viewport, IUnknown *outer_unknown)
4094 {
4095  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4096 
4097  TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4098 
4099  return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4100  outer_unknown);
4101 }
4102 
4103 static HRESULT WINAPI d3d1_CreateViewport(IDirect3D *iface, IDirect3DViewport **viewport, IUnknown *outer_unknown)
4104 {
4105  struct ddraw *ddraw = impl_from_IDirect3D(iface);
4106 
4107  TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4108 
4109  return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4110  outer_unknown);
4111 }
4112 
4113 /*****************************************************************************
4114  * IDirect3D3::FindDevice
4115  *
4116  * This method finds a device with the requested properties and returns a
4117  * device description
4118  *
4119  * Versions 1, 2 and 3
4120  * Params:
4121  * fds: Describes the requested device characteristics
4122  * fdr: Returns the device description
4123  *
4124  * Returns:
4125  * D3D_OK on success
4126  * DDERR_INVALIDPARAMS if no device was found
4127  *
4128  *****************************************************************************/
4130 {
4131  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4132  D3DDEVICEDESC7 desc7;
4133  D3DDEVICEDESC desc1;
4134  HRESULT hr;
4135 
4136  TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4137 
4138  if (!fds || !fdr) return DDERR_INVALIDPARAMS;
4139 
4140  if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH) || (fdr->dwSize != sizeof(D3DFINDDEVICERESULT1) &&
4141  fdr->dwSize != sizeof(D3DFINDDEVICERESULT2) && fdr->dwSize != sizeof(D3DFINDDEVICERESULT)))
4142  return DDERR_INVALIDPARAMS;
4143 
4144  if ((fds->dwFlags & D3DFDS_COLORMODEL)
4145  && fds->dcmColorModel != D3DCOLOR_RGB)
4146  {
4147  WARN("Trying to request a non-RGB D3D color model. Not supported.\n");
4148  return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
4149  }
4150 
4151  if (fds->dwFlags & D3DFDS_GUID)
4152  {
4153  TRACE("Trying to match guid %s.\n", debugstr_guid(&(fds->guid)));
4154  if (!IsEqualGUID(&IID_D3DDEVICE_WineD3D, &fds->guid)
4155  && !IsEqualGUID(&IID_IDirect3DHALDevice, &fds->guid)
4156  && !IsEqualGUID(&IID_IDirect3DRGBDevice, &fds->guid))
4157  {
4158  WARN("No match for this GUID.\n");
4159  return DDERR_NOTFOUND;
4160  }
4161  }
4162 
4163  /* Get the caps */
4164  if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &desc7)))
4165  return hr;
4166 
4167  /* Now return our own GUID */
4168  ddraw_d3dcaps1_from_7(&desc1, &desc7);
4169  fdr->guid = IID_D3DDEVICE_WineD3D;
4170 
4171  if (fdr->dwSize == sizeof(D3DFINDDEVICERESULT1))
4172  {
4174  memcpy(&fdr1->ddHwDesc, &desc1, sizeof(fdr1->ddHwDesc));
4175  memcpy(&fdr1->ddSwDesc, &desc1, sizeof(fdr1->ddSwDesc));
4176  }
4177  else if (fdr->dwSize == sizeof(D3DFINDDEVICERESULT2))
4178  {
4180  memcpy(&fdr2->ddHwDesc, &desc1, sizeof(fdr2->ddHwDesc));
4181  memcpy(&fdr2->ddSwDesc, &desc1, sizeof(fdr2->ddSwDesc));
4182  }
4183  else
4184  {
4185  fdr->ddHwDesc = desc1;
4186  fdr->ddSwDesc = desc1;
4187  }
4188 
4189  TRACE("Returning Wine's wined3d device with (undumped) capabilities.\n");
4190 
4191  return D3D_OK;
4192 }
4193 
4195 {
4196  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4197 
4198  TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4199 
4200  return d3d3_FindDevice(&ddraw->IDirect3D3_iface, fds, fdr);
4201 }
4202 
4204 {
4205  struct ddraw *ddraw = impl_from_IDirect3D(iface);
4206 
4207  TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4208 
4209  return d3d3_FindDevice(&ddraw->IDirect3D3_iface, fds, fdr);
4210 }
4211 
4212 /*****************************************************************************
4213  * IDirect3D7::CreateDevice
4214  *
4215  * Creates an IDirect3DDevice7 interface.
4216  *
4217  * Versions 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to
4218  * DirectDraw surfaces and are created with
4219  * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to
4220  * create the device object and QueryInterfaces for IDirect3DDevice
4221  *
4222  * Params:
4223  * refiid: IID of the device to create
4224  * Surface: Initial rendertarget
4225  * Device: Address to return the interface pointer
4226  *
4227  * Returns:
4228  * D3D_OK on success
4229  * DDERR_OUTOFMEMORY if memory allocation failed
4230  * DDERR_INVALIDPARAMS if a device exists already
4231  *
4232  *****************************************************************************/
4233 static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
4234  IDirectDrawSurface7 *surface, IDirect3DDevice7 **device)
4235 {
4237  struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4238  struct d3d_device *object;
4239  HRESULT hr;
4240 
4241  TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device);
4242 
4244  if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, target, (IUnknown *)surface, 7, &object, NULL)))
4245  {
4246  *device = &object->IDirect3DDevice7_iface;
4247  }
4248  else
4249  {
4250  WARN("Failed to create device, hr %#x.\n", hr);
4251  *device = NULL;
4252  }
4254 
4255  return hr;
4256 }
4257 
4258 static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid,
4259  IDirectDrawSurface4 *surface, IDirect3DDevice3 **device, IUnknown *outer_unknown)
4260 {
4261  struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface4(surface);
4262  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4263  struct d3d_device *device_impl;
4264  HRESULT hr;
4265 
4266  TRACE("iface %p, riid %s, surface %p, device %p, outer_unknown %p.\n",
4267  iface, debugstr_guid(riid), surface, device, outer_unknown);
4268 
4269  if (outer_unknown)
4270  return CLASS_E_NOAGGREGATION;
4271 
4273  if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 3, &device_impl, NULL)))
4274  {
4275  *device = &device_impl->IDirect3DDevice3_iface;
4276  }
4277  else
4278  {
4279  WARN("Failed to create device, hr %#x.\n", hr);
4280  *device = NULL;
4281  }
4283 
4284  return hr;
4285 }
4286 
4287 static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
4288  IDirectDrawSurface *surface, IDirect3DDevice2 **device)
4289 {
4290  struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface(surface);
4291  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4292  struct d3d_device *device_impl;
4293  HRESULT hr;
4294 
4295  TRACE("iface %p, riid %s, surface %p, device %p.\n",
4296  iface, debugstr_guid(riid), surface, device);
4297 
4299  if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 2, &device_impl, NULL)))
4300  {
4301  *device = &device_impl->IDirect3DDevice2_iface;
4302  }
4303  else
4304  {
4305  WARN("Failed to create device, hr %#x.\n", hr);
4306  *device = NULL;
4307  }
4309 
4310  return hr;
4311 }
4312 
4313 /*****************************************************************************
4314  * IDirect3D7::CreateVertexBuffer
4315  *
4316  * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7
4317  * interface.
4318  *
4319  * Versions 3 and 7
4320  *
4321  * Params:
4322  * desc: Requested Vertex buffer properties
4323  * vertex_buffer: Address to return the interface pointer at
4324  * flags: Some flags, should be 0
4325  *
4326  * Returns
4327  * D3D_OK on success
4328  * DDERR_OUTOFMEMORY if memory allocation failed
4329  * DDERR_INVALIDPARAMS if desc or vertex_buffer is NULL
4330  *
4331  *****************************************************************************/
4333  IDirect3DVertexBuffer7 **vertex_buffer, DWORD flags)
4334 {
4335  struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4336  struct d3d_vertex_buffer *object;
4337  HRESULT hr;
4338 
4339  TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x.\n",
4340  iface, desc, vertex_buffer, flags);
4341 
4342  if (!vertex_buffer || !desc) return DDERR_INVALIDPARAMS;
4343 
4344  hr = d3d_vertex_buffer_create(&object, ddraw, desc);
4345  if (hr == D3D_OK)
4346  {
4347  TRACE("Created vertex buffer %p.\n", object);
4348  *vertex_buffer = &object->IDirect3DVertexBuffer7_iface;
4349  }
4350  else
4351  WARN("Failed to create vertex buffer, hr %#x.\n", hr);
4352 
4353  return hr;
4354 }
4355 
4357  IDirect3DVertexBuffer **vertex_buffer, DWORD flags, IUnknown *outer_unknown)
4358 {
4359  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4360  struct d3d_vertex_buffer *object;
4361  HRESULT hr;
4362 
4363  TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x, outer_unknown %p.\n",
4364  iface, desc, vertex_buffer, flags, outer_unknown);
4365 
4366  i