ReactOS  0.4.13-dev-698-g77671f0
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;
636  swapchain_desc.backbuffer_usage = 0;
637  swapchain_desc.backbuffer_count = 1;
638  swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_DISCARD;
639  swapchain_desc.device_window = window;
640  swapchain_desc.windowed = windowed;
642 
643  if (!(ddraw->flags & DDRAW_NO3D))
644  hr = ddraw_attach_d3d_device(ddraw, &swapchain_desc);
645  else
646  hr = wined3d_device_init_gdi(ddraw->wined3d_device, &swapchain_desc);
647 
648  if (FAILED(hr))
649  {
650  ERR("Failed to create swapchain, hr %#x.\n", hr);
651  return hr;
652  }
653 
655  {
656  ERR("Failed to get swapchain.\n");
657  return DDERR_INVALIDPARAMS;
658  }
659 
662 
663  if (ddraw->primary && ddraw->primary->palette)
664  wined3d_swapchain_set_palette(ddraw->wined3d_swapchain, ddraw->primary->palette->wined3d_palette);
665 
666  return DD_OK;
667 }
668 
669 /*****************************************************************************
670  * IDirectDraw7::RestoreDisplayMode
671  *
672  * Restores the display mode to what it was at creation time. Basically.
673  *
674  * Returns
675  * DD_OK on success
676  * DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
677  *
678  *****************************************************************************/
680 {
681  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
682  HRESULT hr;
683 
684  TRACE("iface %p.\n", iface);
685 
687 
688  if (!(ddraw->flags & DDRAW_RESTORE_MODE))
689  {
691  return DD_OK;
692  }
693 
695  {
697  return DDERR_NOEXCLUSIVEMODE;
698  }
699 
702 
704 
706 
707  return hr;
708 }
709 
710 static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
711 {
712  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
713 
714  TRACE("iface %p.\n", iface);
715 
717 }
718 
719 static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
720 {
721  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
722 
723  TRACE("iface %p.\n", iface);
724 
726 }
727 
728 static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
729 {
730  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
731 
732  TRACE("iface %p.\n", iface);
733 
735 }
736 
737 /*****************************************************************************
738  * IDirectDraw7::SetCooperativeLevel
739  *
740  * Sets the cooperative level for the DirectDraw object, and the window
741  * assigned to it. The cooperative level determines the general behavior
742  * of the DirectDraw application
743  *
744  * Warning: This is quite tricky, as it's not really documented which
745  * cooperative levels can be combined with each other. If a game fails
746  * after this function, try to check the cooperative levels passed on
747  * Windows, and if it returns something different.
748  *
749  * If you think that this function caused the failure because it writes a
750  * fixme, be sure to run again with a +ddraw trace.
751  *
752  * What is known about cooperative levels (See the ddraw modes test):
753  * DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN.
754  * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE.
755  * Unlike what msdn claims, DDSCL_NORMAL | DDSCL_FULLSCREEN is allowed.
756  * DDSCL_SETFOCUSWINDOW can be passed only in DDSCL_NORMAL mode, but after that
757  * DDSCL_EXCLUSIVE can be activated.
758  * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES or
759  * DDSCL_CREATEDEVICEWINDOW.
760  *
761  * Handled flags: DDSCL_NORMAL, DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE,
762  * DDSCL_CREATEDEVICEWINDOW, DDSCL_SETDEVICEWINDOW
763  * DDSCL_SETFOCUSWINDOW (partially),
764  * DDSCL_MULTITHREADED (work in progress)
765  * DDSCL_FPUPRESERVE (see device.c)
766  *
767  * Unsure about this: DDSCL_FPUSETUP
768  *
769  * These don't seem very important for wine:
770  * DDSCL_ALLOWREBOOT, DDSCL_NOWINDOWCHANGES, DDSCL_ALLOWMODEX
771  *
772  * Returns:
773  * DD_OK if the cooperative level was set successfully
774  * DDERR_INVALIDPARAMS if the passed cooperative level combination is invalid
775  * DDERR_HWNDALREADYSET if DDSCL_SETFOCUSWINDOW is passed in exclusive mode
776  * (Probably others too, have to investigate)
777  *
778  *****************************************************************************/
780  DWORD cooplevel, BOOL restore_mode_on_normal)
781 {
782  struct wined3d_rendertarget_view *rtv = NULL, *dsv = NULL;
783  struct wined3d_stateblock *stateblock;
784  BOOL restore_state = FALSE;
785  HRESULT hr;
786 
787  TRACE("ddraw %p, window %p, flags %#x, restore_mode_on_normal %x.\n", ddraw, window, cooplevel,
788  restore_mode_on_normal);
789  DDRAW_dump_cooperativelevel(cooplevel);
790 
792 
794  {
795  WARN("Recursive call, returning DD_OK.\n");
796  hr = DD_OK;
797  goto done;
798  }
800 
801  /* Tests suggest that we need one of them: */
802  if(!(cooplevel & (DDSCL_SETFOCUSWINDOW |
803  DDSCL_NORMAL |
804  DDSCL_EXCLUSIVE )))
805  {
806  TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n");
808  goto done;
809  }
810 
811  if ((cooplevel & DDSCL_CREATEDEVICEWINDOW) && !(cooplevel & DDSCL_EXCLUSIVE))
812  {
813  WARN("DDSCL_CREATEDEVICEWINDOW requires DDSCL_EXCLUSIVE.\n");
815  goto done;
816  }
817 
818  /* Handle those levels first which set various hwnds */
819  if ((cooplevel & DDSCL_SETFOCUSWINDOW) && !(cooplevel & DDSCL_CREATEDEVICEWINDOW))
820  {
821  /* This isn't compatible with a lot of flags */
822  if (cooplevel & (DDSCL_MULTITHREADED
828  | DDSCL_NORMAL
830  | DDSCL_FULLSCREEN))
831  {
832  WARN("Called with incompatible flags, returning DDERR_INVALIDPARAMS.\n");
834  goto done;
835  }
836 
838  goto done;
839  }
840 
841  if (cooplevel & DDSCL_EXCLUSIVE)
842  {
843  if (!(cooplevel & DDSCL_FULLSCREEN) || !(window || (cooplevel & DDSCL_CREATEDEVICEWINDOW)))
844  {
845  WARN("DDSCL_EXCLUSIVE requires DDSCL_FULLSCREEN and a window.\n");
847  goto done;
848  }
849 
850  if (cooplevel & DDSCL_CREATEDEVICEWINDOW)
851  {
852  HWND device_window;
853 
854  if (!ddraw->focuswindow && !(cooplevel & DDSCL_SETFOCUSWINDOW))
855  {
856  WARN("No focus window set.\n");
858  goto done;
859  }
860 
861  device_window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "DirectDrawDeviceWnd",
863  NULL, NULL, NULL, NULL);
864  if (!device_window)
865  {
866  ERR("Failed to create window, last error %#x.\n", GetLastError());
867  hr = E_FAIL;
868  goto done;
869  }
870 
871  ShowWindow(device_window, SW_SHOW);
872  TRACE("Created a device window %p.\n", device_window);
873 
874  /* Native apparently leaks the created device window if setting the
875  * focus window below fails. */
877  ddraw->devicewindow = device_window;
878 
879  if (cooplevel & DDSCL_SETFOCUSWINDOW)
880  {
881  if (!window)
882  {
883  hr = DDERR_NOHWND;
884  goto done;
885  }
886 
888  goto done;
889  }
890 
891  window = device_window;
892  }
893  }
894  else
895  {
900  }
901 
903  {
906 
907  if (cooplevel & DDSCL_FULLSCREEN)
908  {
909  struct wined3d_display_mode display_mode;
910 
913  display_mode.width, display_mode.height);
914  }
915  }
916 
917  if ((cooplevel & DDSCL_EXCLUSIVE) && exclusive_window != window)
918  {
921  }
922 
925 
927  {
928  if (!(ddraw->flags & DDRAW_NO3D))
929  {
930  restore_state = TRUE;
931 
933  {
934  ERR("Failed to create stateblock, hr %#x.\n", hr);
935  goto done;
936  }
937 
938  wined3d_stateblock_capture(stateblock);
940  /* Rendering to ddraw->wined3d_frontbuffer. */
942  rtv = NULL;
943  else if (rtv)
945 
948  }
949 
951  }
952 
953  if (FAILED(hr = ddraw_create_swapchain(ddraw, window, !(cooplevel & DDSCL_FULLSCREEN))))
954  ERR("Failed to create swapchain, hr %#x.\n", hr);
955 
956  if (restore_state)
957  {
958  if (dsv)
959  {
962  }
963 
964  if (rtv)
965  {
968  }
969 
970  wined3d_stateblock_apply(stateblock);
971  wined3d_stateblock_decref(stateblock);
972  }
973 
974  if (!(cooplevel & DDSCL_EXCLUSIVE) && (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
975  && restore_mode_on_normal)
976  {
978  if (FAILED(hr))
979  ERR("RestoreDisplayMode failed\n");
980  }
981 
983  && (window != ddraw->dest_window || !(cooplevel & DDSCL_EXCLUSIVE)))
985 
986  if ((cooplevel & DDSCL_EXCLUSIVE)
988  {
990  if (FAILED(hr))
991  {
992  ERR("Failed to acquire focus window, hr %#x.\n", hr);
993  goto done;
994  }
995  }
996 
997  /* Unhandled flags */
998  if (cooplevel & DDSCL_ALLOWREBOOT)
999  WARN("Unhandled flag DDSCL_ALLOWREBOOT, harmless\n");
1000  if (cooplevel & DDSCL_ALLOWMODEX)
1001  WARN("Unhandled flag DDSCL_ALLOWMODEX, harmless\n");
1002  if (cooplevel & DDSCL_FPUSETUP)
1003  WARN("Unhandled flag DDSCL_FPUSETUP, harmless\n");
1004 
1005  if (cooplevel & DDSCL_EXCLUSIVE)
1007  else if (exclusive_ddraw == ddraw)
1009 
1010  /* Store the cooperative_level */
1011  ddraw->cooperative_level = cooplevel;
1013 
1014  TRACE("SetCooperativeLevel returning DD_OK\n");
1015  hr = DD_OK;
1016 done:
1019 
1020  return hr;
1021 }
1022 
1024 {
1025  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1026 
1027  TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1028 
1030 }
1031 
1033 {
1034  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1035 
1036  TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1037 
1039 }
1040 
1042 {
1043  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1044 
1045  TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1046 
1048 }
1049 
1051 {
1052  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1053  HRESULT hr;
1054 
1055  TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
1056 
1058  if (SUCCEEDED(hr))
1060  return hr;
1061 }
1062 
1063 /*****************************************************************************
1064  * IDirectDraw7::SetDisplayMode
1065  *
1066  * Sets the display screen resolution, color depth and refresh frequency
1067  * when in fullscreen mode (in theory).
1068  * Possible return values listed in the SDK suggest that this method fails
1069  * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets
1070  * the display mode in DDSCL_NORMAL mode without an hwnd specified.
1071  * It seems to be valid to pass 0 for With and Height, this has to be tested
1072  * It could mean that the current video mode should be left as-is. (But why
1073  * call it then?)
1074  *
1075  * Params:
1076  * Height, Width: Screen dimension
1077  * BPP: Color depth in Bits per pixel
1078  * Refreshrate: Screen refresh rate
1079  * Flags: Other stuff
1080  *
1081  * Returns
1082  * DD_OK on success
1083  *
1084  *****************************************************************************/
1086  DWORD bpp, DWORD refresh_rate, DWORD flags)
1087 {
1088  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1089  struct wined3d_display_mode mode;
1091  HRESULT hr;
1092 
1093  TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
1094  iface, width, height, bpp, refresh_rate, flags);
1095 
1096  if (force_refresh_rate != 0)
1097  {
1098  TRACE("ForceRefreshRate overriding passed-in refresh rate (%u Hz) to %u Hz\n",
1101  }
1102 
1104 
1106  {
1108  return DDERR_NOEXCLUSIVEMODE;
1109  }
1110 
1111  if (!width || !height)
1112  {
1113  /* It looks like Need for Speed Porsche Unleashed expects DD_OK here. */
1115  return DD_OK;
1116  }
1117 
1118  switch (bpp)
1119  {
1120  case 8: format = WINED3DFMT_P8_UINT; break;
1121  case 15: format = WINED3DFMT_B5G5R5X1_UNORM; break;
1122  case 16: format = WINED3DFMT_B5G6R5_UNORM; break;
1123  case 24: format = WINED3DFMT_B8G8R8_UNORM; break;
1124  case 32: format = WINED3DFMT_B8G8R8X8_UNORM; break;
1125  default: format = WINED3DFMT_UNKNOWN; break;
1126  }
1127 
1128  mode.width = width;
1129  mode.height = height;
1130  mode.refresh_rate = refresh_rate;
1131  mode.format_id = format;
1132  mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
1133 
1134  /* TODO: The possible return values from msdn suggest that the screen mode
1135  * can't be changed if a surface is locked or some drawing is in progress. */
1137  {
1138  if (ddraw->primary)
1139  {
1140  DDSURFACEDESC2 *surface_desc = &ddraw->primary->surface_desc;
1141 
1143  surface_desc->dwWidth, surface_desc->dwHeight, mode.format_id, WINED3D_MULTISAMPLE_NONE, 0)))
1144  ERR("Failed to resize buffers, hr %#x.\n", hr);
1145  else
1146  ddrawformat_from_wined3dformat(&ddraw->primary->surface_desc.u4.ddpfPixelFormat, mode.format_id);
1147  }
1149  }
1150 
1152 
1154 
1155  switch (hr)
1156  {
1158  default: return hr;
1159  }
1160 }
1161 
1164 {
1165  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1166 
1167  TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
1168  iface, width, height, bpp, refresh_rate, flags);
1169 
1170  return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags);
1171 }
1172 
1173 static HRESULT WINAPI ddraw2_SetDisplayMode(IDirectDraw2 *iface,
1174  DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
1175 {
1176  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1177 
1178  TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
1179  iface, width, height, bpp, refresh_rate, flags);
1180 
1181  return ddraw7_SetDisplayMode(&ddraw->IDirectDraw7_iface, width, height, bpp, refresh_rate, flags);
1182 }
1183 
1185 {
1186  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1187 
1188  TRACE("iface %p, width %u, height %u, bpp %u.\n", iface, width, height, bpp);
1189 
1191 }
1192 
1194 {
1195  memset(caps1, 0, sizeof(*caps1));
1196  caps1->dwSize = sizeof(*caps1);
1197  caps1->dwFlags = D3DDD_COLORMODEL
1198  | D3DDD_DEVCAPS
1200  | D3DDD_BCLIPPING
1202  | D3DDD_LINECAPS
1203  | D3DDD_TRICAPS
1208  caps1->dcmColorModel = D3DCOLOR_RGB;
1209  caps1->dwDevCaps = caps7->dwDevCaps;
1210  caps1->dtcTransformCaps.dwSize = sizeof(caps1->dtcTransformCaps);
1212  caps1->bClipping = TRUE;
1213  caps1->dlcLightingCaps.dwSize = sizeof(caps1->dlcLightingCaps);
1220  caps1->dpcLineCaps = caps7->dpcLineCaps;
1221  caps1->dpcTriCaps = caps7->dpcTriCaps;
1224  caps1->dwMaxBufferSize = 0;
1225  caps1->dwMaxVertexCount = 65536;
1226  caps1->dwMinTextureWidth = caps7->dwMinTextureWidth;
1227  caps1->dwMinTextureHeight = caps7->dwMinTextureHeight;
1228  caps1->dwMaxTextureWidth = caps7->dwMaxTextureWidth;
1229  caps1->dwMaxTextureHeight = caps7->dwMaxTextureHeight;
1230  caps1->dwMinStippleWidth = 1;
1231  caps1->dwMinStippleHeight = 1;
1232  caps1->dwMaxStippleWidth = 32;
1233  caps1->dwMaxStippleHeight = 32;
1234  caps1->dwMaxTextureRepeat = caps7->dwMaxTextureRepeat;
1236  caps1->dwMaxAnisotropy = caps7->dwMaxAnisotropy;
1237  caps1->dvGuardBandLeft = caps7->dvGuardBandLeft;
1238  caps1->dvGuardBandTop = caps7->dvGuardBandTop;
1239  caps1->dvGuardBandRight = caps7->dvGuardBandRight;
1240  caps1->dvGuardBandBottom = caps7->dvGuardBandBottom;
1241  caps1->dvExtentsAdjust = caps7->dvExtentsAdjust;
1242  caps1->dwStencilCaps = caps7->dwStencilCaps;
1243  caps1->dwFVFCaps = caps7->dwFVFCaps;
1244  caps1->dwTextureOpCaps = caps7->dwTextureOpCaps;
1247 }
1248 
1250 {
1251  WINED3DCAPS wined3d_caps;
1252  HRESULT hr;
1253 
1254  TRACE("ddraw %p, caps %p.\n", ddraw, caps);
1255 
1256  memset(&wined3d_caps, 0, sizeof(wined3d_caps));
1257 
1261  if (FAILED(hr))
1262  {
1263  WARN("Failed to get device caps, hr %#x.\n", hr);
1264  return hr;
1265  }
1266 
1267  caps->dwDevCaps = wined3d_caps.DevCaps;
1268  caps->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps;
1269  caps->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps;
1270  caps->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps;
1271  caps->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps;
1272  caps->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps;
1273  caps->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps;
1274  caps->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps;
1275  caps->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps;
1276  caps->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps;
1278 
1279  caps->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
1280  caps->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
1281 
1282  caps->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
1283  caps->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio;
1284  caps->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy;
1285  caps->dvMaxVertexW = wined3d_caps.MaxVertexW;
1286 
1287  caps->dvGuardBandLeft = wined3d_caps.GuardBandLeft;
1288  caps->dvGuardBandTop = wined3d_caps.GuardBandTop;
1289  caps->dvGuardBandRight = wined3d_caps.GuardBandRight;
1290  caps->dvGuardBandBottom = wined3d_caps.GuardBandBottom;
1291 
1292  caps->dvExtentsAdjust = wined3d_caps.ExtentsAdjust;
1293  caps->dwStencilCaps = wined3d_caps.StencilCaps;
1294 
1295  caps->dwFVFCaps = wined3d_caps.FVFCaps;
1296  caps->dwTextureOpCaps = wined3d_caps.TextureOpCaps;
1297 
1298  caps->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps;
1299  caps->dwMaxActiveLights = wined3d_caps.MaxActiveLights;
1300 
1301  /* Remove all non-d3d7 caps */
1302  caps->dwDevCaps &= (
1310 
1311  caps->dwStencilCaps &= (
1315 
1316  /* FVF caps ?*/
1317 
1318  caps->dwTextureOpCaps &= (
1327 
1328  caps->dwVertexProcessingCaps &= (
1331 
1332  caps->dpcLineCaps.dwMiscCaps &= (
1336 
1337  caps->dpcLineCaps.dwRasterCaps &= (
1346 
1347  caps->dpcLineCaps.dwZCmpCaps &= (
1351 
1352  caps->dpcLineCaps.dwSrcBlendCaps &= (
1358 
1359  caps->dpcLineCaps.dwDestBlendCaps &= (
1365 
1366  caps->dpcLineCaps.dwAlphaCmpCaps &= (
1370 
1371  caps->dpcLineCaps.dwShadeCaps &= (
1379 
1380  caps->dpcLineCaps.dwTextureCaps &= (
1385 
1386  caps->dpcLineCaps.dwTextureFilterCaps &= (
1393 
1397 
1399  {
1400  /* DirectX7 always has the np2 flag set, no matter what the card
1401  * supports. Some old games (Rollcage) check the caps incorrectly.
1402  * If wined3d supports nonpow2 textures it also has np2 conditional
1403  * support. */
1405  }
1406 
1407  /* Fill the missing members, and do some fixup */
1408  caps->dpcLineCaps.dwSize = sizeof(caps->dpcLineCaps);
1417  caps->dpcLineCaps.dwStippleWidth = 32;
1418  caps->dpcLineCaps.dwStippleHeight = 32;
1419  /* Use the same for the TriCaps */
1420  caps->dpcTriCaps = caps->dpcLineCaps;
1421 
1424  caps->dwMinTextureWidth = 1;
1425  caps->dwMinTextureHeight = 1;
1426 
1427  /* Convert DWORDs safely to WORDs */
1428  caps->wMaxTextureBlendStages = min(wined3d_caps.MaxTextureBlendStages, 0xffff);
1429  caps->wMaxSimultaneousTextures = min(wined3d_caps.MaxSimultaneousTextures, 0xffff);
1431  caps->wMaxVertexBlendMatrices = min(wined3d_caps.MaxVertexBlendMatrices, 0xffff);
1432 
1433  caps->deviceGUID = IID_IDirect3DTnLHalDevice;
1434 
1435  caps->dwReserved1 = 0;
1436  caps->dwReserved2 = 0;
1437  caps->dwReserved3 = 0;
1438  caps->dwReserved4 = 0;
1439 
1440  return DD_OK;
1441 }
1442 
1444 {
1445  DDCAPS *caps = ctx;
1446 
1447  switch (format->u1.dwZBufferBitDepth)
1448  {
1449  case 8:
1450  caps->dwZBufferBitDepths |= DDBD_8;
1451  break;
1452  case 16:
1453  caps->dwZBufferBitDepths |= DDBD_16;
1454  break;
1455  case 24:
1456  caps->dwZBufferBitDepths |= DDBD_24;
1457  break;
1458  case 32:
1459  caps->dwZBufferBitDepths |= DDBD_32;
1460  break;
1461  }
1462  return D3DENUMRET_OK;
1463 }
1464 
1465 /*****************************************************************************
1466  * IDirectDraw7::GetCaps
1467  *
1468  * Returns the drives capabilities
1469  *
1470  * Used for version 1, 2, 4 and 7
1471  *
1472  * Params:
1473  * DriverCaps: Structure to write the Hardware accelerated caps to
1474  * HelCaps: Structure to write the emulation caps to
1475  *
1476  * Returns
1477  * This implementation returns DD_OK only
1478  *
1479  *****************************************************************************/
1480 static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DDCAPS *HELCaps)
1481 {
1482  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1483  DDCAPS caps;
1484  WINED3DCAPS winecaps;
1485  HRESULT hr;
1486  DDSCAPS2 ddscaps = {0, 0, 0, {0}};
1487 
1488  TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, DriverCaps, HELCaps);
1489 
1490  /* One structure must be != NULL */
1491  if (!DriverCaps && !HELCaps)
1492  {
1493  WARN("Invalid parameters.\n");
1494  return DDERR_INVALIDPARAMS;
1495  }
1496 
1497  memset(&caps, 0, sizeof(caps));
1498  memset(&winecaps, 0, sizeof(winecaps));
1499  caps.dwSize = sizeof(caps);
1500 
1503  if (FAILED(hr))
1504  {
1505  WARN("Failed to get device caps, %#x.\n", hr);
1507  return hr;
1508  }
1509 
1510  hr = IDirectDraw7_GetAvailableVidMem(iface, &ddscaps, &caps.dwVidMemTotal, &caps.dwVidMemFree);
1511  if (FAILED(hr))
1512  {
1513  WARN("IDirectDraw7::GetAvailableVidMem failed\n");
1515  return hr;
1516  }
1517 
1518  hr = IDirectDraw7_GetFourCCCodes(iface, &caps.dwNumFourCCCodes, NULL);
1520  if (FAILED(hr))
1521  {
1522  WARN("IDirectDraw7::GetFourCCCodes failed\n");
1523  return hr;
1524  }
1525 
1526  caps.dwCaps = winecaps.ddraw_caps.caps;
1527  caps.dwCaps2 = winecaps.ddraw_caps.caps2;
1528  caps.dwCKeyCaps = winecaps.ddraw_caps.color_key_caps;
1529  caps.dwFXCaps = winecaps.ddraw_caps.fx_caps;
1530  caps.dwPalCaps = DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE;
1531  caps.ddsCaps.dwCaps = winecaps.ddraw_caps.dds_caps;
1532  caps.dwSVBCaps = winecaps.ddraw_caps.svb_caps;
1533  caps.dwSVBCKeyCaps = winecaps.ddraw_caps.svb_color_key_caps;
1534  caps.dwSVBFXCaps = winecaps.ddraw_caps.svb_fx_caps;
1535  caps.dwVSBCaps = winecaps.ddraw_caps.vsb_caps;
1536  caps.dwVSBCKeyCaps = winecaps.ddraw_caps.vsb_color_key_caps;
1537  caps.dwVSBFXCaps = winecaps.ddraw_caps.vsb_fx_caps;
1538  caps.dwSSBCaps = winecaps.ddraw_caps.ssb_caps;
1539  caps.dwSSBCKeyCaps = winecaps.ddraw_caps.ssb_color_key_caps;
1540  caps.dwSSBFXCaps = winecaps.ddraw_caps.ssb_fx_caps;
1541 
1542  caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
1543  caps.dwAlignStrideAlign = DDRAW_STRIDE_ALIGNMENT;
1544 
1545  caps.ddsOldCaps.dwCaps = caps.ddsCaps.dwCaps;
1546 
1547  IDirect3D7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, &IID_IDirect3DHALDevice, enum_zbuffer, &caps);
1548 
1549  if(DriverCaps)
1550  {
1551  DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
1552  if (TRACE_ON(ddraw))
1553  {
1554  TRACE("Driver Caps :\n");
1555  DDRAW_dump_DDCAPS(DriverCaps);
1556  }
1557 
1558  }
1559  if(HELCaps)
1560  {
1561  DD_STRUCT_COPY_BYSIZE(HELCaps, &caps);
1562  if (TRACE_ON(ddraw))
1563  {
1564  TRACE("HEL Caps :\n");
1565  DDRAW_dump_DDCAPS(HELCaps);
1566  }
1567  }
1568 
1569  return DD_OK;
1570 }
1571 
1572 static HRESULT WINAPI ddraw4_GetCaps(IDirectDraw4 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1573 {
1574  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1575 
1576  TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1577 
1578  return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1579 }
1580 
1581 static HRESULT WINAPI ddraw2_GetCaps(IDirectDraw2 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1582 {
1583  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1584 
1585  TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1586 
1587  return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1588 }
1589 
1590 static HRESULT WINAPI ddraw1_GetCaps(IDirectDraw *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1591 {
1592  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1593 
1594  TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1595 
1596  return ddraw7_GetCaps(&ddraw->IDirectDraw7_iface, driver_caps, hel_caps);
1597 }
1598 
1599 /*****************************************************************************
1600  * IDirectDraw7::Compact
1601  *
1602  * No idea what it does, MSDN says it's not implemented.
1603  *
1604  * Returns
1605  * DD_OK, but this is unchecked
1606  *
1607  *****************************************************************************/
1609 {
1610  TRACE("iface %p.\n", iface);
1611 
1612  return DD_OK;
1613 }
1614 
1615 static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface)
1616 {
1617  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1618 
1619  TRACE("iface %p.\n", iface);
1620 
1622 }
1623 
1624 static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface)
1625 {
1626  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1627 
1628  TRACE("iface %p.\n", iface);
1629 
1631 }
1632 
1633 static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface)
1634 {
1635  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1636 
1637  TRACE("iface %p.\n", iface);
1638 
1640 }
1641 
1642 /*****************************************************************************
1643  * IDirectDraw7::GetDisplayMode
1644  *
1645  * Returns information about the current display mode
1646  *
1647  * Exists in versions 1, 2, 4 and 7
1648  *
1649  * Params:
1650  * DDSD: Address of a surface description structure to write the info to
1651  *
1652  * Returns
1653  * DD_OK
1654  *
1655  *****************************************************************************/
1657 {
1658  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1659  struct wined3d_display_mode mode;
1660  HRESULT hr;
1661 
1662  TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
1663 
1664  /* This seems sane */
1665  if (!DDSD || (DDSD->dwSize != sizeof(DDSURFACEDESC) && DDSD->dwSize != sizeof(DDSURFACEDESC2)))
1666  return DDERR_INVALIDPARAMS;
1667 
1669 
1671  {
1672  ERR("Failed to get display mode, hr %#x.\n", hr);
1674  return hr;
1675  }
1676 
1677  memset(DDSD, 0, DDSD->dwSize);
1678  DDSD->dwSize = sizeof(*DDSD);
1680  DDSD->dwWidth = mode.width;
1681  DDSD->dwHeight = mode.height;
1682  DDSD->u2.dwRefreshRate = 60;
1683  DDSD->ddsCaps.dwCaps = 0;
1684  DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat);
1685  ddrawformat_from_wined3dformat(&DDSD->u4.ddpfPixelFormat, mode.format_id);
1686  DDSD->u1.lPitch = mode.width * DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount / 8;
1687 
1688  if(TRACE_ON(ddraw))
1689  {
1690  TRACE("Returning surface desc :\n");
1692  }
1693 
1695 
1696  return DD_OK;
1697 }
1698 
1699 static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *surface_desc)
1700 {
1701  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1702 
1703  TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1704 
1705  return ddraw7_GetDisplayMode(&ddraw->IDirectDraw7_iface, surface_desc);
1706 }
1707 
1708 static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *surface_desc)
1709 {
1710  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1711  HRESULT hr;
1712 
1713  TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1714 
1716  if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
1717  return hr;
1718 }
1719 
1720 static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *surface_desc)
1721 {
1722  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1723  HRESULT hr;
1724 
1725  TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1726 
1728  if (SUCCEEDED(hr)) surface_desc->dwSize = sizeof(*surface_desc);
1729  return hr;
1730 }
1731 
1732 /*****************************************************************************
1733  * IDirectDraw7::GetFourCCCodes
1734  *
1735  * Returns an array of supported FourCC codes.
1736  *
1737  * Exists in versions 1, 2, 4 and 7
1738  *
1739  * Params:
1740  * NumCodes: Contains the number of Codes that Codes can carry. Returns the number
1741  * of enumerated codes
1742  * Codes: Pointer to an array of DWORDs where the supported codes are written
1743  * to
1744  *
1745  * Returns
1746  * Always returns DD_OK, as it's a stub for now
1747  *
1748  *****************************************************************************/
1749 static HRESULT WINAPI ddraw7_GetFourCCCodes(IDirectDraw7 *iface, DWORD *NumCodes, DWORD *Codes)
1750 {
1751  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1752  static const enum wined3d_format_id formats[] =
1753  {
1757  };
1758  struct wined3d_display_mode mode;
1759  DWORD count = 0, i, outsize;
1760  HRESULT hr;
1761 
1762  TRACE("iface %p, codes_count %p, codes %p.\n", iface, NumCodes, Codes);
1763 
1765  {
1766  ERR("Failed to get display mode, hr %#x.\n", hr);
1767  return hr;
1768  }
1769 
1770  outsize = NumCodes && Codes ? *NumCodes : 0;
1771 
1772  for (i = 0; i < ARRAY_SIZE(formats); ++i)
1773  {
1775  mode.format_id, 0, WINED3D_RTYPE_TEXTURE_2D, formats[i])))
1776  {
1777  if (count < outsize)
1778  Codes[count] = formats[i];
1779  ++count;
1780  }
1781  }
1782  if(NumCodes) {
1783  TRACE("Returning %u FourCC codes\n", count);
1784  *NumCodes = count;
1785  }
1786 
1787  return DD_OK;
1788 }
1789 
1790 static HRESULT WINAPI ddraw4_GetFourCCCodes(IDirectDraw4 *iface, DWORD *codes_count, DWORD *codes)
1791 {
1792  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1793 
1794  TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1795 
1796  return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1797 }
1798 
1799 static HRESULT WINAPI ddraw2_GetFourCCCodes(IDirectDraw2 *iface, DWORD *codes_count, DWORD *codes)
1800 {
1801  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1802 
1803  TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1804 
1805  return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1806 }
1807 
1808 static HRESULT WINAPI ddraw1_GetFourCCCodes(IDirectDraw *iface, DWORD *codes_count, DWORD *codes)
1809 {
1810  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1811 
1812  TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1813 
1814  return ddraw7_GetFourCCCodes(&ddraw->IDirectDraw7_iface, codes_count, codes);
1815 }
1816 
1818 {
1819  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1820  struct wined3d_display_mode mode;
1821  HRESULT hr;
1822 
1823  TRACE("iface %p, frequency %p.\n", iface, frequency);
1824 
1828  if (FAILED(hr))
1829  {
1830  WARN("Failed to get display mode, hr %#x.\n", hr);
1831  return hr;
1832  }
1833 
1834  *frequency = mode.refresh_rate;
1835 
1836  return DD_OK;
1837 }
1838 
1840 {
1841  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1842 
1843  TRACE("iface %p, frequency %p.\n", iface, frequency);
1844 
1846 }
1847 
1849 {
1850  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1851 
1852  TRACE("iface %p, frequency %p.\n", iface, frequency);
1853 
1855 }
1856 
1858 {
1859  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1860 
1861  TRACE("iface %p, frequency %p.\n", iface, frequency);
1862 
1864 }
1865 
1867 {
1868  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1869  struct wined3d_raster_status raster_status;
1870  HRESULT hr;
1871 
1872  TRACE("iface %p, status %p.\n", iface, status);
1873 
1874  if(!status)
1875  return DDERR_INVALIDPARAMS;
1876 
1880  if (FAILED(hr))
1881  {
1882  WARN("Failed to get raster status, hr %#x.\n", hr);
1883  return hr;
1884  }
1885 
1886  *status = raster_status.in_vblank;
1887 
1888  return DD_OK;
1889 }
1890 
1892 {
1893  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1894 
1895  TRACE("iface %p, status %p.\n", iface, status);
1896 
1898 }
1899 
1901 {
1902  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
1903 
1904  TRACE("iface %p, status %p.\n", iface, status);
1905 
1907 }
1908 
1910 {
1911  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
1912 
1913  TRACE("iface %p, status %p.\n", iface, status);
1914 
1916 }
1917 
1918 /*****************************************************************************
1919  * IDirectDraw7::GetAvailableVidMem
1920  *
1921  * Returns the total and free video memory
1922  *
1923  * Params:
1924  * caps: Specifies the memory type asked for
1925  * total: Pointer to a DWORD to be filled with the total memory
1926  * free: Pointer to a DWORD to be filled with the free memory
1927  *
1928  * Returns
1929  * DD_OK on success
1930  * DDERR_INVALIDPARAMS if free and total are NULL
1931  *
1932  *****************************************************************************/
1934  DWORD *free)
1935 {
1936  unsigned int framebuffer_size, total_vidmem, free_vidmem;
1937  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
1938  struct wined3d_display_mode mode;
1939  HRESULT hr = DD_OK;
1940 
1941  TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1942 
1943  if (!total && !free)
1944  return DDERR_INVALIDPARAMS;
1945 
1946  if (TRACE_ON(ddraw))
1947  {
1948  TRACE("Asked for memory with description: ");
1949  DDRAW_dump_DDSCAPS2(caps);
1950  }
1952 
1953  /* Todo: System memory vs local video memory vs non-local video memory
1954  * The MSDN also mentions differences between texture memory and other
1955  * resources, but that's not important
1956  */
1957 
1958  /* Some applications (e.g. 3DMark 2000) assume that the reported amount of
1959  * video memory doesn't include the memory used by the default framebuffer.
1960  */
1962  {
1963  WARN("Failed to get display mode, hr %#x.\n", hr);
1965  return hr;
1966  }
1968  mode.format_id, mode.width);
1969  framebuffer_size *= mode.height;
1970 
1971  if (free)
1972  {
1974  *free = framebuffer_size > free_vidmem ? 0 : free_vidmem - framebuffer_size;
1975  TRACE("Free video memory %#x.\n", *free);
1976  }
1977 
1978  if (total)
1979  {
1980  struct wined3d_adapter_identifier desc = {0};
1981 
1983  total_vidmem = min(UINT_MAX, desc.video_memory);
1984  *total = framebuffer_size > total_vidmem ? 0 : total_vidmem - framebuffer_size;
1985  TRACE("Total video memory %#x.\n", *total);
1986  }
1987 
1989 
1990  return hr;
1991 }
1992 
1993 static HRESULT WINAPI ddraw4_GetAvailableVidMem(IDirectDraw4 *iface,
1994  DDSCAPS2 *caps, DWORD *total, DWORD *free)
1995 {
1996  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
1997 
1998  TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1999 
2000  return ddraw7_GetAvailableVidMem(&ddraw->IDirectDraw7_iface, caps, total, free);
2001 }
2002 
2003 static HRESULT WINAPI ddraw2_GetAvailableVidMem(IDirectDraw2 *iface,
2004  DDSCAPS *caps, DWORD *total, DWORD *free)
2005 {
2006  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2007  DDSCAPS2 caps2;
2008 
2009  TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
2010 
2011  DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
2012  return ddraw7_GetAvailableVidMem(&ddraw->IDirectDraw7_iface, &caps2, total, free);
2013 }
2014 
2015 /*****************************************************************************
2016  * IDirectDraw7::Initialize
2017  *
2018  * Initializes a DirectDraw interface.
2019  *
2020  * Params:
2021  * GUID: Interface identifier. Well, don't know what this is really good
2022  * for
2023  *
2024  * Returns
2025  * Returns DD_OK on the first call,
2026  * DDERR_ALREADYINITIALIZED on repeated calls
2027  *
2028  *****************************************************************************/
2030 {
2031  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2032 
2033  TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2034 
2035  if (ddraw->flags & DDRAW_INITIALIZED)
2036  return DDERR_ALREADYINITIALIZED;
2037 
2038  /* FIXME: To properly take the GUID into account we should call
2039  * ddraw_init() here instead of in DDRAW_Create(). */
2040  if (guid)
2041  FIXME("Ignoring guid %s.\n", debugstr_guid(guid));
2042 
2044  return DD_OK;
2045 }
2046 
2047 static HRESULT WINAPI ddraw4_Initialize(IDirectDraw4 *iface, GUID *guid)
2048 {
2049  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2050 
2051  TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2052 
2054 }
2055 
2056 static HRESULT WINAPI ddraw2_Initialize(IDirectDraw2 *iface, GUID *guid)
2057 {
2058  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2059 
2060  TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2061 
2063 }
2064 
2065 static HRESULT WINAPI ddraw1_Initialize(IDirectDraw *iface, GUID *guid)
2066 {
2067  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2068 
2069  TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
2070 
2072 }
2073 
2074 static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID riid)
2075 {
2076  TRACE("iface %p, riid %s.\n", iface, debugstr_guid(riid));
2077 
2078  return DDERR_ALREADYINITIALIZED;
2079 }
2080 
2081 /*****************************************************************************
2082  * IDirectDraw7::FlipToGDISurface
2083  *
2084  * "Makes the surface that the GDI writes to the primary surface"
2085  * Looks like some windows specific thing we don't have to care about.
2086  * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to
2087  * show error boxes ;)
2088  * Well, just return DD_OK.
2089  *
2090  * Returns:
2091  * Always returns DD_OK
2092  *
2093  *****************************************************************************/
2095 {
2096  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2097 
2098  TRACE("iface %p.\n", iface);
2099 
2101 
2102  if (ddraw->primary)
2104 
2105  return DD_OK;
2106 }
2107 
2108 static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface)
2109 {
2110  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2111 
2112  TRACE("iface %p.\n", iface);
2113 
2115 }
2116 
2117 static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface)
2118 {
2119  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2120 
2121  TRACE("iface %p.\n", iface);
2122 
2124 }
2125 
2126 static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface)
2127 {
2128  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2129 
2130  TRACE("iface %p.\n", iface);
2131 
2133 }
2134 
2135 /*****************************************************************************
2136  * IDirectDraw7::WaitForVerticalBlank
2137  *
2138  * This method allows applications to get in sync with the vertical blank
2139  * interval.
2140  * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't
2141  * redraw the screen, most likely because of this stub
2142  *
2143  * Parameters:
2144  * Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT
2145  * or DDWAITVB_BLOCKEND
2146  * h: Not used, according to MSDN
2147  *
2148  * Returns:
2149  * Always returns DD_OK
2150  *
2151  *****************************************************************************/
2153 {
2154  static BOOL hide;
2155 
2156  TRACE("iface %p, flags %#x, event %p.\n", iface, Flags, event);
2157 
2158  /* This function is called often, so print the fixme only once */
2159  if(!hide)
2160  {
2161  FIXME("iface %p, flags %#x, event %p stub!\n", iface, Flags, event);
2162  hide = TRUE;
2163  }
2164 
2165  /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */
2167  return DDERR_UNSUPPORTED; /* unchecked */
2168 
2169  return DD_OK;
2170 }
2171 
2173 {
2174  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2175 
2176  TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2177 
2179 }
2180 
2182 {
2183  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2184 
2185  TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2186 
2188 }
2189 
2191 {
2192  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2193 
2194  TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
2195 
2197 }
2198 
2200 {
2201  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2202  struct wined3d_raster_status raster_status;
2203  HRESULT hr;
2204 
2205  TRACE("iface %p, line %p.\n", iface, Scanline);
2206 
2210  if (FAILED(hr))
2211  {
2212  WARN("Failed to get raster status, hr %#x.\n", hr);
2213  return hr;
2214  }
2215 
2216  *Scanline = raster_status.scan_line;
2217 
2218  if (raster_status.in_vblank)
2220 
2221  return DD_OK;
2222 }
2223 
2224 static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line)
2225 {
2226  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2227 
2228  TRACE("iface %p, line %p.\n", iface, line);
2229 
2231 }
2232 
2233 static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line)
2234 {
2235  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2236 
2237  TRACE("iface %p, line %p.\n", iface, line);
2238 
2240 }
2241 
2242 static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line)
2243 {
2244  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2245 
2246  TRACE("iface %p, line %p.\n", iface, line);
2247 
2249 }
2250 
2252 {
2253  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2254 
2255  TRACE("iface %p.\n", iface);
2256 
2258 }
2259 
2260 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface)
2261 {
2262  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2263 
2264  TRACE("iface %p.\n", iface);
2265 
2267 }
2268 
2269 /*****************************************************************************
2270  * IDirectDraw7::GetGDISurface
2271  *
2272  * Returns the surface that GDI is treating as the primary surface.
2273  * For Wine this is the front buffer
2274  *
2275  * Params:
2276  * GDISurface: Address to write the surface pointer to
2277  *
2278  * Returns:
2279  * DD_OK if the surface was found
2280  * DDERR_NOTFOUND if the GDI surface wasn't found
2281  *
2282  *****************************************************************************/
2284 {
2285  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2286 
2287  TRACE("iface %p, surface %p.\n", iface, GDISurface);
2288 
2290 
2291  if (!(*GDISurface = &ddraw->primary->IDirectDrawSurface7_iface))
2292  {
2293  WARN("Primary not created yet.\n");
2295  return DDERR_NOTFOUND;
2296  }
2297  IDirectDrawSurface7_AddRef(*GDISurface);
2298 
2300 
2301  return DD_OK;
2302 }
2303 
2304 static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface)
2305 {
2306  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2307  struct ddraw_surface *surface_impl;
2308  IDirectDrawSurface7 *surface7;
2309  HRESULT hr;
2310 
2311  TRACE("iface %p, surface %p.\n", iface, surface);
2312 
2314  if (FAILED(hr))
2315  {
2316  *surface = NULL;
2317  return hr;
2318  }
2319  surface_impl = impl_from_IDirectDrawSurface7(surface7);
2320  *surface = &surface_impl->IDirectDrawSurface4_iface;
2321  IDirectDrawSurface4_AddRef(*surface);
2322  IDirectDrawSurface7_Release(surface7);
2323 
2324  return hr;
2325 }
2326 
2327 static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface)
2328 {
2329  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2330  struct ddraw_surface *surface_impl;
2331  IDirectDrawSurface7 *surface7;
2332  HRESULT hr;
2333 
2334  TRACE("iface %p, surface %p.\n", iface, surface);
2335 
2337  if (FAILED(hr))
2338  {
2339  *surface = NULL;
2340  return hr;
2341  }
2342  surface_impl = impl_from_IDirectDrawSurface7(surface7);
2343  *surface = &surface_impl->IDirectDrawSurface_iface;
2344  IDirectDrawSurface_AddRef(*surface);
2345  IDirectDrawSurface7_Release(surface7);
2346 
2347  return hr;
2348 }
2349 
2350 static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface)
2351 {
2352  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2353  struct ddraw_surface *surface_impl;
2354  IDirectDrawSurface7 *surface7;
2355  HRESULT hr;
2356 
2357  TRACE("iface %p, surface %p.\n", iface, surface);
2358 
2360  if (FAILED(hr))
2361  {
2362  *surface = NULL;
2363  return hr;
2364  }
2365  surface_impl = impl_from_IDirectDrawSurface7(surface7);
2366  *surface = &surface_impl->IDirectDrawSurface_iface;
2367  IDirectDrawSurface_AddRef(*surface);
2368  IDirectDrawSurface7_Release(surface7);
2369 
2370  return hr;
2371 }
2372 
2374 {
2376  void *context;
2377 };
2378 
2380 {
2381  struct displaymodescallback_context *cbcontext = context;
2383 
2384  DDSD2_to_DDSD(surface_desc, &desc);
2385  return cbcontext->func(&desc, cbcontext->context);
2386 }
2387 
2388 /*****************************************************************************
2389  * IDirectDraw7::EnumDisplayModes
2390  *
2391  * Enumerates the supported Display modes. The modes can be filtered with
2392  * the DDSD parameter.
2393  *
2394  * Params:
2395  * Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES. For old ddraw
2396  * versions (3 and older?) this is reserved and must be 0.
2397  * DDSD: Surface description to filter the modes
2398  * Context: Pointer passed back to the callback function
2399  * cb: Application-provided callback function
2400  *
2401  * Returns:
2402  * DD_OK on success
2403  * DDERR_INVALIDPARAMS if the callback wasn't set
2404  *
2405  *****************************************************************************/
2408 {
2409  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2410  struct wined3d_display_mode *enum_modes = NULL;
2411  struct wined3d_display_mode mode;
2412  unsigned int modenum, fmt;
2413  DDSURFACEDESC2 callback_sd;
2414  unsigned enum_mode_count = 0, enum_mode_array_size = 16;
2416 
2417  static const enum wined3d_format_id checkFormatList[] =
2418  {
2422  };
2423 
2424  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2425  iface, Flags, DDSD, Context, cb);
2426 
2427  if (!cb)
2428  return DDERR_INVALIDPARAMS;
2429 
2430  if (!(enum_modes = heap_alloc(enum_mode_array_size * sizeof(*enum_modes))))
2431  return DDERR_OUTOFMEMORY;
2432 
2434 
2435  pixelformat.dwSize = sizeof(pixelformat);
2436  for(fmt = 0; fmt < ARRAY_SIZE(checkFormatList); fmt++)
2437  {
2438  modenum = 0;
2441  {
2442  BOOL found = FALSE;
2443  unsigned i;
2444 
2446  if (DDSD)
2447  {
2448  if (DDSD->dwFlags & DDSD_WIDTH && mode.width != DDSD->dwWidth)
2449  continue;
2450  if (DDSD->dwFlags & DDSD_HEIGHT && mode.height != DDSD->dwHeight)
2451  continue;
2452  if (DDSD->dwFlags & DDSD_REFRESHRATE && mode.refresh_rate != DDSD->u2.dwRefreshRate)
2453  continue;
2454  if (DDSD->dwFlags & DDSD_PIXELFORMAT
2455  && pixelformat.u1.dwRGBBitCount != DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount)
2456  continue;
2457  }
2458 
2459  /* DX docs state EnumDisplayMode should return only unique modes */
2460  for (i = 0; i < enum_mode_count; i++)
2461  {
2462  if (enum_modes[i].width == mode.width && enum_modes[i].height == mode.height
2463  && enum_modes[i].format_id == mode.format_id
2464  && (enum_modes[i].refresh_rate == mode.refresh_rate || !(Flags & DDEDM_REFRESHRATES)))
2465  {
2466  found = TRUE;
2467  break;
2468  }
2469  }
2470  if(found) continue;
2471 
2472  memset(&callback_sd, 0, sizeof(callback_sd));
2473  callback_sd.dwSize = sizeof(callback_sd);
2474  callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
2475 
2477  if (Flags & DDEDM_REFRESHRATES)
2478  callback_sd.u2.dwRefreshRate = mode.refresh_rate;
2479 
2480  callback_sd.dwWidth = mode.width;
2481  callback_sd.dwHeight = mode.height;
2482 
2483  callback_sd.u4.ddpfPixelFormat=pixelformat;
2484 
2485  /* Calc pitch and DWORD align like MSDN says */
2486  callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.width;
2487  callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3;
2488 
2489  TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
2490  callback_sd.u2.dwRefreshRate);
2491 
2492  if(cb(&callback_sd, Context) == DDENUMRET_CANCEL)
2493  {
2494  TRACE("Application asked to terminate the enumeration\n");
2495  heap_free(enum_modes);
2497  return DD_OK;
2498  }
2499 
2500  if (enum_mode_count == enum_mode_array_size)
2501  {
2502  struct wined3d_display_mode *new_enum_modes;
2503 
2504  enum_mode_array_size *= 2;
2505  if (!(new_enum_modes = heap_realloc(enum_modes, enum_mode_array_size * sizeof(*new_enum_modes))))
2506  {
2507  heap_free(enum_modes);
2509  return DDERR_OUTOFMEMORY;
2510  }
2511 
2512  enum_modes = new_enum_modes;
2513  }
2514  enum_modes[enum_mode_count++] = mode;
2515  }
2516  }
2517 
2518  TRACE("End of enumeration\n");
2519  heap_free(enum_modes);
2521 
2522  return DD_OK;
2523 }
2524 
2525 static HRESULT WINAPI ddraw4_EnumDisplayModes(IDirectDraw4 *iface, DWORD flags,
2526  DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMMODESCALLBACK2 callback)
2527 {
2528  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2529 
2530  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2531  iface, flags, surface_desc, context, callback);
2532 
2534 }
2535 
2536 static HRESULT WINAPI ddraw2_EnumDisplayModes(IDirectDraw2 *iface, DWORD flags,
2537  DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2538 {
2539  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2540  struct displaymodescallback_context cbcontext;
2541  DDSURFACEDESC2 surface_desc2;
2542 
2543  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2544  iface, flags, surface_desc, context, callback);
2545 
2546  cbcontext.func = callback;
2547  cbcontext.context = context;
2548 
2549  if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2551  surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2552 }
2553 
2554 static HRESULT WINAPI ddraw1_EnumDisplayModes(IDirectDraw *iface, DWORD flags,
2555  DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2556 {
2557  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
2558  struct displaymodescallback_context cbcontext;
2559  DDSURFACEDESC2 surface_desc2;
2560 
2561  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2562  iface, flags, surface_desc, context, callback);
2563 
2564  cbcontext.func = callback;
2565  cbcontext.context = context;
2566 
2567  if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2569  surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumDisplayModesCallbackThunk);
2570 }
2571 
2572 /*****************************************************************************
2573  * IDirectDraw7::EvaluateMode
2574  *
2575  * Used with IDirectDraw7::StartModeTest to test video modes.
2576  * EvaluateMode is used to pass or fail a mode, and continue with the next
2577  * mode
2578  *
2579  * Params:
2580  * Flags: DDEM_MODEPASSED or DDEM_MODEFAILED
2581  * Timeout: Returns the amount of seconds left before the mode would have
2582  * been failed automatically
2583  *
2584  * Returns:
2585  * This implementation always DD_OK, because it's a stub
2586  *
2587  *****************************************************************************/
2589 {
2590  FIXME("iface %p, flags %#x, timeout %p stub!\n", iface, Flags, Timeout);
2591 
2592  /* When implementing this, implement it in WineD3D */
2593 
2594  return DD_OK;
2595 }
2596 
2597 /*****************************************************************************
2598  * IDirectDraw7::GetDeviceIdentifier
2599  *
2600  * Returns the device identifier, which gives information about the driver
2601  * Our device identifier is defined at the beginning of this file.
2602  *
2603  * Params:
2604  * DDDI: Address for the returned structure
2605  * Flags: Can be DDGDI_GETHOSTIDENTIFIER
2606  *
2607  * Returns:
2608  * On success it returns DD_OK
2609  * DDERR_INVALIDPARAMS if DDDI is NULL
2610  *
2611  *****************************************************************************/
2614 {
2615  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2616  struct wined3d_adapter_identifier adapter_id;
2617  HRESULT hr = S_OK;
2618 
2619  TRACE("iface %p, device_identifier %p, flags %#x.\n", iface, DDDI, Flags);
2620 
2621  if (!DDDI)
2622  return DDERR_INVALIDPARAMS;
2623 
2625  {
2626  /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D
2627  * host adapter, if there's a secondary 3D adapter. This doesn't apply
2628  * to any modern hardware, nor is it interesting for Wine, so ignore it.
2629  * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4
2630  * bytes too long. So only copy the relevant part of the structure
2631  */
2632 
2634  return DD_OK;
2635  }
2636 
2637  /* Drakan: Order of the Flame expects accurate D3D device information from ddraw */
2638  adapter_id.driver = DDDI->szDriver;
2639  adapter_id.driver_size = sizeof(DDDI->szDriver);
2640  adapter_id.description = DDDI->szDescription;
2641  adapter_id.description_size = sizeof(DDDI->szDescription);
2642  adapter_id.device_name_size = 0;
2646  if (FAILED(hr)) return hr;
2647 
2648  DDDI->liDriverVersion = adapter_id.driver_version;
2649  DDDI->dwVendorId = adapter_id.vendor_id;
2650  DDDI->dwDeviceId = adapter_id.device_id;
2651  DDDI->dwSubSysId = adapter_id.subsystem_id;
2652  DDDI->dwRevision = adapter_id.revision;
2653  DDDI->guidDeviceIdentifier = adapter_id.device_identifier;
2654  DDDI->dwWHQLLevel = adapter_id.whql_level;
2655  return DD_OK;
2656 }
2657 
2658 static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface,
2659  DDDEVICEIDENTIFIER *identifier, DWORD flags)
2660 {
2661  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2662  DDDEVICEIDENTIFIER2 identifier2;
2663  HRESULT hr;
2664 
2665  TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags);
2666 
2668  DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier);
2669 
2670  return hr;
2671 }
2672 
2673 /*****************************************************************************
2674  * IDirectDraw7::GetSurfaceFromDC
2675  *
2676  * Returns the Surface for a GDI device context handle.
2677  * Is this related to IDirectDrawSurface::GetDC ???
2678  *
2679  * Params:
2680  * hdc: hdc to return the surface for
2681  * Surface: Address to write the surface pointer to
2682  *
2683  * Returns:
2684  * Always returns DD_OK because it's a stub
2685  *
2686  *****************************************************************************/
2688  HDC dc, IDirectDrawSurface7 **surface)
2689 {
2690  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2691  struct ddraw_surface *surface_impl;
2692 
2693  TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2694 
2695  if (!surface)
2696  return E_INVALIDARG;
2697 
2698  if (!dc)
2699  goto done;
2700 
2703  {
2704  if (surface_impl->dc != dc)
2705  continue;
2706 
2707  TRACE("Found surface %p for dc %p.\n", surface_impl, dc);
2708  *surface = &surface_impl->IDirectDrawSurface7_iface;
2709  IDirectDrawSurface7_AddRef(*surface);
2711  return DD_OK;
2712  }
2714 
2715 done:
2716  TRACE("No surface found for dc %p.\n", dc);
2717  *surface = NULL;
2718  return DDERR_NOTFOUND;
2719 }
2720 
2721 static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc,
2722  IDirectDrawSurface4 **surface)
2723 {
2724  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2725  struct ddraw_surface *surface_impl;
2726  IDirectDrawSurface7 *surface7;
2727  HRESULT hr;
2728 
2729  TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2730 
2731  if (!surface) return E_INVALIDARG;
2732 
2734  if (FAILED(hr))
2735  {
2736  *surface = NULL;
2737  return hr;
2738  }
2739  surface_impl = impl_from_IDirectDrawSurface7(surface7);
2740  /* Tests say this is true */
2741  *surface = (IDirectDrawSurface4 *)&surface_impl->IDirectDrawSurface_iface;
2742  IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
2743  IDirectDrawSurface7_Release(surface7);
2744 
2745  return hr;
2746 }
2747 
2749 {
2750  IDirectDrawSurface_Restore(surface);
2751  IDirectDrawSurface_Release(surface);
2752 
2753  return DDENUMRET_OK;
2754 }
2755 
2757 {
2758  TRACE("iface %p.\n", iface);
2759 
2760  return IDirectDraw7_EnumSurfaces(iface, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
2762 }
2763 
2764 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
2765 {
2766  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2767 
2768  TRACE("iface %p.\n", iface);
2769 
2771 }
2772 
2773 /*****************************************************************************
2774  * IDirectDraw7::StartModeTest
2775  *
2776  * Tests the specified video modes to update the system registry with
2777  * refresh rate information. StartModeTest starts the mode test,
2778  * EvaluateMode is used to fail or pass a mode. If EvaluateMode
2779  * isn't called within 15 seconds, the mode is failed automatically
2780  *
2781  * As refresh rates are handled by the X server, I don't think this
2782  * Method is important
2783  *
2784  * Params:
2785  * Modes: An array of mode specifications
2786  * NumModes: The number of modes in Modes
2787  * Flags: Some flags...
2788  *
2789  * Returns:
2790  * Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
2791  * if no modes are passed, DDERR_INVALIDPARAMS is returned,
2792  * otherwise DD_OK
2793  *
2794  *****************************************************************************/
2796 {
2797  FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n",
2798  iface, Modes, NumModes, Flags);
2799 
2800  /* This looks sane */
2801  if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
2802 
2803  /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
2804  * As it is not, DDERR_TESTFINISHED is returned
2805  * (hopefully that's correct
2806  *
2807  if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
2808  * well, that value doesn't (yet) exist in the wine headers, so ignore it
2809  */
2810 
2811  return DD_OK;
2812 }
2813 
2815  IDirectDrawSurface7 **surface, IUnknown *outer_unknown)
2816 {
2817  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
2818  struct ddraw_surface *impl;
2819  HRESULT hr;
2820 
2821  TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2822  iface, surface_desc, surface, outer_unknown);
2823 
2825 
2827  {
2828  WARN("Cooperative level not set.\n");
2831  }
2832 
2833  if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2834  {
2835  WARN("Application supplied invalid surface descriptor\n");
2837  return DDERR_INVALIDPARAMS;
2838  }
2839 
2840  __TRY
2841  {
2842  *surface = NULL;
2843  }
2845  {
2846  WARN("Surface pointer %p is invalid.\n", surface);
2848  return DDERR_INVALIDPARAMS;
2849  }
2850  __ENDTRY;
2851 
2853  {
2854  if (TRACE_ON(ddraw))
2855  {
2856  TRACE(" (%p) Requesting surface desc :\n", iface);
2858  }
2859 
2860  WARN("Application tried to create an explicit front or back buffer\n");
2862  return DDERR_INVALIDCAPS;
2863  }
2864 
2865  hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 7);
2867  if (FAILED(hr))
2868  return hr;
2869 
2870  *surface = &impl->IDirectDrawSurface7_iface;
2871  IDirectDraw7_AddRef(iface);
2872  impl->ifaceToRelease = (IUnknown *)iface;
2873 
2874  return hr;
2875 }
2876 
2877 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
2878  DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown)
2879 {
2880  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
2881  struct ddraw_surface *impl;
2882  HRESULT hr;
2883 
2884  TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2885  iface, surface_desc, surface, outer_unknown);
2886 
2888 
2890  {
2891  WARN("Cooperative level not set.\n");
2894  }
2895 
2896  if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
2897  {
2898  WARN("Application supplied invalid surface descriptor\n");
2900  return DDERR_INVALIDPARAMS;
2901  }
2902 
2903  __TRY
2904  {
2905  *surface = NULL;
2906  }
2908  {
2909  WARN("Surface pointer %p is invalid.\n", surface);
2911  return DDERR_INVALIDPARAMS;
2912  }
2913  __ENDTRY;
2914 
2916  {
2917  if (TRACE_ON(ddraw))
2918  {
2919  TRACE(" (%p) Requesting surface desc :\n", iface);
2921  }
2922 
2923  WARN("Application tried to create an explicit front or back buffer\n");
2925  return DDERR_INVALIDCAPS;
2926  }
2927 
2928  hr = ddraw_surface_create(ddraw, surface_desc, &impl, outer_unknown, 4);
2930  if (FAILED(hr))
2931  return hr;
2932 
2933  *surface = &impl->IDirectDrawSurface4_iface;
2934  IDirectDraw4_AddRef(iface);
2935  impl->ifaceToRelease = (IUnknown *)iface;
2936 
2937  return hr;
2938 }
2939 
2940 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
2941  DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
2942 {
2943  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
2944  struct ddraw_surface *impl;
2945  HRESULT hr;
2946  DDSURFACEDESC2 surface_desc2;
2947 
2948  TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
2949  iface, surface_desc, surface, outer_unknown);
2950 
2952 
2954  {
2955  WARN("Cooperative level not set.\n");
2958  }
2959 
2960  if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
2961  {
2962  WARN("Application supplied invalid surface descriptor\n");
2964  return DDERR_INVALIDPARAMS;
2965  }
2966 
2967  __TRY
2968  {
2969  *surface = NULL;
2970  }
2972  {
2973  WARN("Surface pointer %p is invalid.\n", surface);
2975  return DDERR_INVALIDPARAMS;
2976  }
2977  __ENDTRY;
2978 
2979  DDSD_to_DDSD2(surface_desc, &surface_desc2);
2981  {
2982  if (TRACE_ON(ddraw))
2983  {
2984  TRACE(" (%p) Requesting surface desc :\n", iface);
2986  }
2987 
2988  WARN("Application tried to create an explicit front or back buffer\n");
2990  return DDERR_INVALIDCAPS;
2991  }
2992 
2993  hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 2);
2995  if (FAILED(hr))
2996  return hr;
2997 
2998  *surface = &impl->IDirectDrawSurface_iface;
2999  impl->ifaceToRelease = NULL;
3000 
3001  return hr;
3002 }
3003 
3004 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
3005  DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3006 {
3007  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3008  struct ddraw_surface *impl;
3009  HRESULT hr;
3010  DDSURFACEDESC2 surface_desc2;
3011 
3012  TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3013  iface, surface_desc, surface, outer_unknown);
3014 
3016 
3018  {
3019  WARN("Cooperative level not set.\n");
3022  }
3023 
3024  if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3025  {
3026  WARN("Application supplied invalid surface descriptor\n");
3028  return DDERR_INVALIDPARAMS;
3029  }
3030 
3031  __TRY
3032  {
3033  *surface = NULL;
3034  }
3036  {
3037  WARN("Surface pointer %p is invalid.\n", surface);
3039  return DDERR_INVALIDPARAMS;
3040  }
3041  __ENDTRY;
3042 
3047  {
3048  WARN("Application tried to create an explicit front or back buffer.\n");
3050  return DDERR_INVALIDCAPS;
3051  }
3052 
3053  DDSD_to_DDSD2(surface_desc, &surface_desc2);
3054  hr = ddraw_surface_create(ddraw, &surface_desc2, &impl, outer_unknown, 1);
3056  if (FAILED(hr))
3057  return hr;
3058 
3059  *surface = &impl->IDirectDrawSurface_iface;
3060  impl->ifaceToRelease = NULL;
3061 
3062  return hr;
3063 }
3064 
3065 static BOOL
3067  const DDPIXELFORMAT *provided)
3068 {
3069  /* Some flags must be present in both or neither for a match. */
3070  static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
3073 
3074  if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3075  return FALSE;
3076 
3077  if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
3078  return FALSE;
3079 
3080  if (requested->dwFlags & DDPF_FOURCC)
3081  if (requested->dwFourCC != provided->dwFourCC)
3082  return FALSE;
3083 
3084  if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA
3086  if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount)
3087  return FALSE;
3088 
3089  if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3091  if (requested->u2.dwRBitMask != provided->u2.dwRBitMask)
3092  return FALSE;
3093 
3094  if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV))
3095  if (requested->u3.dwGBitMask != provided->u3.dwGBitMask)
3096  return FALSE;
3097 
3098  /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3099  if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3100  |DDPF_BUMPDUDV))
3101  if (requested->u4.dwBBitMask != provided->u4.dwBBitMask)
3102  return FALSE;
3103 
3104  if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
3105  if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask)
3106  return FALSE;
3107 
3108  return TRUE;
3109 }
3110 
3111 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided)
3112 {
3113  struct compare_info
3114  {
3115  DWORD flag;
3116  ptrdiff_t offset;
3117  size_t size;
3118  };
3119 
3120 #define CMP(FLAG, FIELD) \
3121  { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3122  sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3123 
3124  static const struct compare_info compare[] =
3125  {
3126  CMP(ALPHABITDEPTH, dwAlphaBitDepth),
3127  CMP(BACKBUFFERCOUNT, u5.dwBackBufferCount),
3128  CMP(CAPS, ddsCaps),
3129  CMP(CKDESTBLT, ddckCKDestBlt),
3130  CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */),
3131  CMP(CKSRCBLT, ddckCKSrcBlt),
3132  CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
3133  CMP(HEIGHT, dwHeight),
3134  CMP(LINEARSIZE, u1 /* dwLinearSize */),
3135  CMP(LPSURFACE, lpSurface),
3136  CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */),
3137  CMP(PITCH, u1 /* lPitch */),
3138  /* PIXELFORMAT: manual */
3139  CMP(REFRESHRATE, u2 /* dwRefreshRate */),
3140  CMP(TEXTURESTAGE, dwTextureStage),
3141  CMP(WIDTH, dwWidth),
3142  /* ZBUFFERBITDEPTH: "obsolete" */
3143  };
3144 
3145 #undef CMP
3146 
3147  unsigned int i;
3148 
3149  if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3150  return FALSE;
3151 
3152  for (i=0; i < ARRAY_SIZE(compare); i++)
3153  {
3154  if (requested->dwFlags & compare[i].flag
3155  && memcmp((const char *)provided + compare[i].offset,
3156  (const char *)requested + compare[i].offset,
3157  compare[i].size) != 0)
3158  return FALSE;
3159  }
3160 
3161  if (requested->dwFlags & DDSD_PIXELFORMAT)
3162  {
3164  &provided->u4.ddpfPixelFormat))
3165  return FALSE;
3166  }
3167 
3168  return TRUE;
3169 }
3170 
3172 {
3174  void *context;
3175 };
3176 
3178 {
3180  void *context;
3181 };
3182 
3184  DDSURFACEDESC2 *surface_desc, void *context)
3185 {
3186  struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3187  struct surfacescallback2_context *cbcontext = context;
3188 
3189  IDirectDrawSurface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
3190  IDirectDrawSurface7_Release(surface);
3191 
3192  return cbcontext->func(&surface_impl->IDirectDrawSurface4_iface,
3193  surface_desc, cbcontext->context);
3194 }
3195 
3197  DDSURFACEDESC2 *surface_desc, void *context)
3198 {
3199  struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
3200  struct surfacescallback_context *cbcontext = context;
3201 
3202  IDirectDrawSurface_AddRef(&surface_impl->IDirectDrawSurface_iface);
3203  IDirectDrawSurface7_Release(surface);
3204 
3205  return cbcontext->func(&surface_impl->IDirectDrawSurface_iface,
3206  (DDSURFACEDESC *)surface_desc, cbcontext->context);
3207 }
3208 
3209 /*****************************************************************************
3210  * IDirectDraw7::EnumSurfaces
3211  *
3212  * Loops through all surfaces attached to this device and calls the
3213  * application callback. This can't be relayed to WineD3DDevice,
3214  * because some WineD3DSurfaces' parents are IParent objects
3215  *
3216  * Params:
3217  * Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3218  * DDSD: Description to filter for
3219  * Context: Application-provided pointer, it's passed unmodified to the
3220  * Callback function
3221  * Callback: Address to call for each surface
3222  *
3223  * Returns:
3224  * DDERR_INVALIDPARAMS if the callback is NULL
3225  * DD_OK on success
3226  *
3227  *****************************************************************************/
3230 {
3231  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3232  struct ddraw_surface *surf;
3234 
3235  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3236  iface, Flags, DDSD, Context, Callback);
3237 
3238  if (!Callback)
3239  return DDERR_INVALIDPARAMS;
3240 
3242  {
3243  IDirectDrawSurface7 *surface;
3244  DDSURFACEDESC2 testdesc;
3245  HRESULT hr;
3246 
3247  if (match_flags != DDENUMSURFACES_MATCH)
3248  return DDERR_INVALIDPARAMS;
3249 
3250  if (!DDSD)
3251  return DDERR_INVALIDPARAMS;
3252 
3253  memcpy(&testdesc, DDSD, sizeof(testdesc));
3254  if (!(testdesc.dwFlags & DDSD_WIDTH))
3255  {
3256  testdesc.dwFlags |= DDSD_WIDTH;
3257  testdesc.dwWidth = 512;
3258  }
3259  if (!(testdesc.dwFlags & DDSD_HEIGHT))
3260  {
3261  testdesc.dwFlags |= DDSD_HEIGHT;
3262  testdesc.dwHeight = 512;
3263  }
3264 
3265  hr = IDirectDraw7_CreateSurface(iface, &testdesc, &surface, NULL);
3266  if (SUCCEEDED(hr))
3267  {
3268  surf = unsafe_impl_from_IDirectDrawSurface7(surface);
3269  Callback(NULL, &surf->surface_desc, Context);
3270  IDirectDrawSurface7_Release(surface);
3271  }
3272  else
3273  ERR("Failed to create surface, hr %#x.\n", hr);
3274  }
3275  else if (Flags & DDENUMSURFACES_DOESEXIST)
3276  {
3277  BOOL all, nomatch;
3279  struct list *entry, *entry2;
3280 
3281  /* a combination of match flags is not allowed */
3282  if (match_flags != 0 &&
3283  match_flags != DDENUMSURFACES_ALL &&
3284  match_flags != DDENUMSURFACES_MATCH &&
3285  match_flags != DDENUMSURFACES_NOMATCH)
3286  return DDERR_INVALIDPARAMS;
3287 
3288  all = (Flags & DDENUMSURFACES_ALL) != 0;
3289  nomatch = (Flags & DDENUMSURFACES_NOMATCH) != 0;
3290 
3291  if (!all && !DDSD)
3292  return DDERR_INVALIDPARAMS;
3293 
3295 
3296  /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
3298  {
3299  surf = LIST_ENTRY(entry, struct ddraw_surface, surface_list_entry);
3300 
3301  if (!surf->iface_count)
3302  {
3303  WARN("Not enumerating surface %p because it doesn't have any references.\n", surf);
3304  continue;
3305  }
3306 
3307  if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc)))
3308  {
3309  TRACE("Enumerating surface %p.\n", surf);
3310  desc = surf->surface_desc;
3311  IDirectDrawSurface7_AddRef(&surf->IDirectDrawSurface7_iface);
3313  {
3315  return DD_OK;
3316  }
3317  }
3318  }
3319 
3321  }
3322  else
3323  return DDERR_INVALIDPARAMS;
3324 
3325  return DD_OK;
3326 }
3327 
3328 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags,
3330 {
3331  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3332  struct surfacescallback2_context cbcontext;
3333 
3334  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3335  iface, flags, surface_desc, context, callback);
3336 
3337  cbcontext.func = callback;
3338  cbcontext.context = context;
3339 
3340  return ddraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, flags, surface_desc,
3341  &cbcontext, EnumSurfacesCallback2Thunk);
3342 }
3343 
3344 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags,
3346 {
3347  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3348  struct surfacescallback_context cbcontext;
3349  DDSURFACEDESC2 surface_desc2;
3350 
3351  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3352  iface, flags, surface_desc, context, callback);
3353 
3354  cbcontext.func = callback;
3355  cbcontext.context = context;
3356 
3357  if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3359  surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3360 }
3361 
3362 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags,
3364 {
3365  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3366  struct surfacescallback_context cbcontext;
3367  DDSURFACEDESC2 surface_desc2;
3368 
3369  TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3370  iface, flags, surface_desc, context, callback);
3371 
3372  cbcontext.func = callback;
3373  cbcontext.context = context;
3374 
3375  if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3377  surface_desc ? &surface_desc2 : NULL, &cbcontext, EnumSurfacesCallbackThunk);
3378 }
3379 
3380 /*****************************************************************************
3381  * DirectDrawCreateClipper (DDRAW.@)
3382  *
3383  * Creates a new IDirectDrawClipper object.
3384  *
3385  * Params:
3386  * Clipper: Address to write the interface pointer to
3387  * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3388  * NULL
3389  *
3390  * Returns:
3391  * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3392  * E_OUTOFMEMORY if allocating the object failed
3393  *
3394  *****************************************************************************/
3395 HRESULT WINAPI DirectDrawCreateClipper(DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3396 {
3397  struct ddraw_clipper *object;
3398  HRESULT hr;
3399 
3400  TRACE("flags %#x, clipper %p, outer_unknown %p.\n",
3401  flags, clipper, outer_unknown);
3402 
3403  if (outer_unknown)
3404  return CLASS_E_NOAGGREGATION;
3405 
3407 
3408  if (!(object = heap_alloc_zero(sizeof(*object))))
3409  {
3411  return E_OUTOFMEMORY;
3412  }
3413 
3414  hr = ddraw_clipper_init(object);
3415  if (FAILED(hr))
3416  {
3417  WARN("Failed to initialize clipper, hr %#x.\n", hr);
3418  heap_free(object);
3420  return hr;
3421  }
3422 
3423  TRACE("Created clipper %p.\n", object);
3424  *clipper = &object->IDirectDrawClipper_iface;
3426 
3427  return DD_OK;
3428 }
3429 
3430 /*****************************************************************************
3431  * IDirectDraw7::CreateClipper
3432  *
3433  * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3434  *
3435  *****************************************************************************/
3437  IDirectDrawClipper **Clipper, IUnknown *UnkOuter)
3438 {
3439  TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3440  iface, Flags, Clipper, UnkOuter);
3441 
3442  return DirectDrawCreateClipper(Flags, Clipper, UnkOuter);
3443 }
3444 
3445 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface, DWORD flags,
3446  IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3447 {
3448  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3449 
3450  TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3451  iface, flags, clipper, outer_unknown);
3452 
3453  return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3454 }
3455 
3456 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface,
3457  DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3458 {
3459  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3460 
3461  TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3462  iface, flags, clipper, outer_unknown);
3463 
3464  return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3465 }
3466 
3467 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface,
3468  DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
3469 {
3470  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3471 
3472  TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3473  iface, flags, clipper, outer_unknown);
3474 
3475  return ddraw7_CreateClipper(&ddraw->IDirectDraw7_iface, flags, clipper, outer_unknown);
3476 }
3477 
3478 /*****************************************************************************
3479  * IDirectDraw7::CreatePalette
3480  *
3481  * Creates a new IDirectDrawPalette object
3482  *
3483  * Params:
3484  * Flags: The flags for the new clipper
3485  * ColorTable: Color table to assign to the new clipper
3486  * Palette: Address to write the interface pointer to
3487  * UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3488  * NULL
3489  *
3490  * Returns:
3491  * CLASS_E_NOAGGREGATION if UnkOuter != NULL
3492  * E_OUTOFMEMORY if allocating the object failed
3493  *
3494  *****************************************************************************/
3496  PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter)
3497 {
3498  struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
3499  struct ddraw_palette *object;
3500  HRESULT hr;
3501 
3502  TRACE("iface %p, flags %#x, color_table %p, palette %p, outer_unknown %p.\n",
3503  iface, Flags, ColorTable, Palette, pUnkOuter);
3504 
3505  if (pUnkOuter)
3506  return CLASS_E_NOAGGREGATION;
3507 
3509 
3510  /* The refcount test shows that a cooplevel is required for this */
3511  if (!ddraw->cooperative_level)
3512  {
3513  WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
3516  }
3517 
3518  if (!(object = heap_alloc(sizeof(*object))))
3519  {
3520  ERR("Out of memory when allocating memory for a palette implementation\n");
3522  return E_OUTOFMEMORY;
3523  }
3524 
3525  hr = ddraw_palette_init(object, ddraw, Flags, ColorTable);
3526  if (FAILED(hr))
3527  {
3528  WARN("Failed to initialize palette, hr %#x.\n", hr);
3529  heap_free(object);
3531  return hr;
3532  }
3533 
3534  TRACE("Created palette %p.\n", object);
3535  *Palette = &object->IDirectDrawPalette_iface;
3537 
3538  return DD_OK;
3539 }
3540 
3541 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags, PALETTEENTRY *entries,
3542  IDirectDrawPalette **palette, IUnknown *outer_unknown)
3543 {
3544  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3545  HRESULT hr;
3546 
3547  TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3548  iface, flags, entries, palette, outer_unknown);
3549 
3550  hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3551  if (SUCCEEDED(hr) && *palette)
3552  {
3554  IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3555  IDirectDraw4_AddRef(iface);
3556  impl->ifaceToRelease = (IUnknown *)iface;
3557  }
3558  return hr;
3559 }
3560 
3561 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags,
3562  PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3563 {
3564  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3565  HRESULT hr;
3566 
3567  TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3568  iface, flags, entries, palette, outer_unknown);
3569 
3570  hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3571  if (SUCCEEDED(hr) && *palette)
3572  {
3574  IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3575  impl->ifaceToRelease = NULL;
3576  }
3577 
3578  return hr;
3579 }
3580 
3581 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags,
3582  PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
3583 {
3584  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3585  HRESULT hr;
3586 
3587  TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
3588  iface, flags, entries, palette, outer_unknown);
3589 
3590  hr = ddraw7_CreatePalette(&ddraw->IDirectDraw7_iface, flags, entries, palette, outer_unknown);
3591  if (SUCCEEDED(hr) && *palette)
3592  {
3594  IDirectDraw7_Release(&ddraw->IDirectDraw7_iface);
3595  impl->ifaceToRelease = NULL;
3596  }
3597 
3598  return hr;
3599 }
3600 
3601 /*****************************************************************************
3602  * IDirectDraw7::DuplicateSurface
3603  *
3604  * Duplicates a surface. The surface memory points to the same memory as
3605  * the original surface, and it's released when the last surface referencing
3606  * it is released. I guess that's beyond Wine's surface management right now
3607  * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
3608  * test application to implement this)
3609  *
3610  * Params:
3611  * Src: Address of the source surface
3612  * Dest: Address to write the new surface pointer to
3613  *
3614  * Returns:
3615  * See IDirectDraw7::CreateSurface
3616  *
3617  *****************************************************************************/
3620 {
3621  struct ddraw_surface *src_surface = unsafe_impl_from_IDirectDrawSurface7(Src);
3622 
3623  FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest);
3624 
3625  /* For now, simply create a new, independent surface */
3626  return IDirectDraw7_CreateSurface(iface, &src_surface->surface_desc, Dest, NULL);
3627 }
3628 
3629 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSurface4 *src,
3630  IDirectDrawSurface4 **dst)
3631 {
3633  struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
3634  struct ddraw_surface *dst_impl;
3635  IDirectDrawSurface7 *dst7;
3636  HRESULT hr;
3637 
3638  TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3639 
3641  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3642  if (FAILED(hr))
3643  {
3644  *dst = NULL;
3645  return hr;
3646  }
3647  dst_impl = impl_from_IDirectDrawSurface7(dst7);
3648  *dst = &dst_impl->IDirectDrawSurface4_iface;
3649  IDirectDrawSurface4_AddRef(*dst);
3650  IDirectDrawSurface7_Release(dst7);
3651 
3652  return hr;
3653 }
3654 
3655 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface,
3656  IDirectDrawSurface *src, IDirectDrawSurface **dst)
3657 {
3659  struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
3660  struct ddraw_surface *dst_impl;
3661  IDirectDrawSurface7 *dst7;
3662  HRESULT hr;
3663 
3664  TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3665 
3667  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3668  if (FAILED(hr))
3669  return hr;
3670  dst_impl = impl_from_IDirectDrawSurface7(dst7);
3671  *dst = &dst_impl->IDirectDrawSurface_iface;
3672  IDirectDrawSurface_AddRef(*dst);
3673  IDirectDrawSurface7_Release(dst7);
3674 
3675  return hr;
3676 }
3677 
3678 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src,
3679  IDirectDrawSurface **dst)
3680 {
3682  struct ddraw *ddraw = impl_from_IDirectDraw(iface);
3683  struct ddraw_surface *dst_impl;
3684  IDirectDrawSurface7 *dst7;
3685  HRESULT hr;
3686 
3687  TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
3688 
3690  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, &dst7);
3691  if (FAILED(hr))
3692  return hr;
3693  dst_impl = impl_from_IDirectDrawSurface7(dst7);
3694  *dst = &dst_impl->IDirectDrawSurface_iface;
3695  IDirectDrawSurface_AddRef(*dst);
3696  IDirectDrawSurface7_Release(dst7);
3697 
3698  return hr;
3699 }
3700 
3701 /*****************************************************************************
3702  * IDirect3D7::EnumDevices
3703  *
3704  * The EnumDevices method for IDirect3D7. It enumerates all supported
3705  * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated.
3706  *
3707  * Params:
3708  * callback: Function to call for each enumerated device
3709  * context: Pointer to pass back to the app
3710  *
3711  * Returns:
3712  * D3D_OK, or the return value of the GetCaps call
3713  *
3714  *****************************************************************************/
3716 {
3717  struct ddraw *ddraw = impl_from_IDirect3D7(iface);
3718  D3DDEVICEDESC7 device_desc7;
3719  DWORD dev_caps;
3720  HRESULT hr;
3721  size_t i;
3722 
3723  TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3724 
3725  if (!callback)
3726  return DDERR_INVALIDPARAMS;
3727 
3729 
3730  if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
3731  {
3733  return hr;
3734  }
3735 
3736  dev_caps = device_desc7.dwDevCaps;
3737 
3738  for (i = 0; i < ARRAY_SIZE(device_list7); i++)
3739  {
3740  HRESULT ret;
3741 
3742  device_desc7.deviceGUID = *device_list7[i].device_guid;
3743  device_desc7.dwDevCaps = dev_caps & ~device_list7[i].remove_caps;
3744 
3745  ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context);
3746  if (ret != DDENUMRET_OK)
3747  {
3748  TRACE("Application cancelled the enumeration.\n");
3750  return D3D_OK;
3751  }
3752  }
3753 
3754  TRACE("End of enumeration.\n");
3755 
3757 
3758  return D3D_OK;
3759 }
3760 
3761 /*****************************************************************************
3762  * IDirect3D3::EnumDevices
3763  *
3764  * Enumerates all supported Direct3DDevice interfaces. This is the
3765  * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
3766  *
3767  * Versions 1, 2 and 3
3768  *
3769  * Params:
3770  * callback: Application-provided routine to call for each enumerated device
3771  * Context: Pointer to pass to the callback
3772  *
3773  * Returns:
3774  * D3D_OK on success,
3775  * The result of IDirect3DImpl_GetCaps if it failed
3776  *
3777  *****************************************************************************/
3779 {
3780  static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
3781 
3782  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3783  D3DDEVICEDESC device_desc1, hal_desc, hel_desc;
3784  D3DDEVICEDESC7 device_desc7;
3785  HRESULT hr;
3786 
3787  /* Some games (Motoracer 2 demo) have the bad idea to modify the device
3788  * name string. Let's put the string in a sufficiently sized array in
3789  * writable memory. */
3790  char device_name[50];
3791  strcpy(device_name,"Direct3D HEL");
3792 
3793  TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3794 
3795  if (!callback)
3796  return DDERR_INVALIDPARAMS;
3797 
3799 
3800  if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
3801  {
3803  return hr;
3804  }
3805  ddraw_d3dcaps1_from_7(&device_desc1, &device_desc7);
3806 
3807  /* Do I have to enumerate the reference id? Note from old d3d7:
3808  * "It seems that enumerating the reference IID on Direct3D 1 games
3809  * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
3810  *
3811  * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers,
3812  * EnumReference which enables / disables enumerating the reference
3813  * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The
3814  * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk
3815  * demo directory suggest this.
3816  *
3817  * Some games(GTA 2) seem to use the second enumerated device, so I have
3818  * to enumerate at least 2 devices. So enumerate the reference device to
3819  * have 2 devices.
3820  *
3821  * Other games (Rollcage) tell emulation and hal device apart by certain
3822  * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a
3823  * limitation flag), and it refuses all devices that have the perspective
3824  * flag set. This way it refuses the emulation device, and HAL devices
3825  * never have POW2 unset in d3d7 on windows. */
3826  if (ddraw->d3dversion != 1)
3827  {
3828  static CHAR reference_description[] = "RGB Direct3D emulation";
3829 
3830  TRACE("Enumerating WineD3D D3DDevice interface.\n");
3831  hal_desc = device_desc1;
3832  hel_desc = device_desc1;
3833  /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */
3838  /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */
3839  hal_desc.dcmColorModel = 0;
3840  /* RGB, RAMP and MMX devices cannot report HAL hardware flags */
3841  hal_desc.dwFlags = 0;
3842 
3843  hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
3844  device_name, &hal_desc, &hel_desc, context);
3845  if (hr != D3DENUMRET_OK)
3846  {
3847  TRACE("Application cancelled the enumeration.\n");
3849  return D3D_OK;
3850  }
3851  }
3852 
3853  strcpy(device_name,"Direct3D HAL");
3854 
3855  TRACE("Enumerating HAL Direct3D device.\n");
3856  hal_desc = device_desc1;
3857  hel_desc = device_desc1;
3858 
3859  /* The hal device does not have the pow2 flag set in hel, but in hal. */
3864  /* HAL devices have a HEL dcmColorModel of 0 */
3865  hel_desc.dcmColorModel = 0;
3866 
3867  hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description,
3868  device_name, &hal_desc, &hel_desc, context);
3869  if (hr != D3DENUMRET_OK)
3870  {
3871  TRACE("Application cancelled the enumeration.\n");
3873  return D3D_OK;
3874  }
3875 
3876  TRACE("End of enumeration.\n");
3877 
3879 
3880  return D3D_OK;
3881 }
3882 
3884 {
3885  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3886 
3887  TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3888 
3890 }
3891 
3893 {
3894  struct ddraw *ddraw = impl_from_IDirect3D(iface);
3895 
3896  TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
3897 
3899 }
3900 
3901 /*****************************************************************************
3902  * IDirect3D3::CreateLight
3903  *
3904  * Creates an IDirect3DLight interface. This interface is used in
3905  * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
3906  * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
3907  * uses the IDirect3DDevice7 interface with D3D7 lights.
3908  *
3909  * Versions 1, 2 and 3
3910  *
3911  * Params:
3912  * light: Address to store the new interface pointer
3913  * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3914  * Must be NULL
3915  *
3916  * Returns:
3917  * D3D_OK on success
3918  * DDERR_OUTOFMEMORY if memory allocation failed
3919  * CLASS_E_NOAGGREGATION if outer_unknown != NULL
3920  *
3921  *****************************************************************************/
3922 static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light,
3923  IUnknown *outer_unknown)
3924 {
3925  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3926  struct d3d_light *object;
3927 
3928  TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3929 
3930  if (outer_unknown)
3931  return CLASS_E_NOAGGREGATION;
3932 
3933  if (!(object = heap_alloc_zero(sizeof(*object))))
3934  {
3935  ERR("Failed to allocate light memory.\n");
3936  return DDERR_OUTOFMEMORY;
3937  }
3938 
3939  d3d_light_init(object, ddraw);
3940 
3941  TRACE("Created light %p.\n", object);
3942  *light = &object->IDirect3DLight_iface;
3943 
3944  return D3D_OK;
3945 }
3946 
3947 static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3948 {
3949  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
3950 
3951  TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3952 
3953  return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
3954 }
3955 
3956 static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown)
3957 {
3958  struct ddraw *ddraw = impl_from_IDirect3D(iface);
3959 
3960  TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
3961 
3962  return d3d3_CreateLight(&ddraw->IDirect3D3_iface, light, outer_unknown);
3963 }
3964 
3965 /*****************************************************************************
3966  * IDirect3D3::CreateMaterial
3967  *
3968  * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
3969  * and older versions. The IDirect3DMaterial implementation wraps its
3970  * functionality to IDirect3DDevice7::SetMaterial and friends.
3971  *
3972  * Versions 1, 2 and 3
3973  *
3974  * Params:
3975  * material: Address to store the new interface's pointer to
3976  * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
3977  * Must be NULL
3978  *
3979  * Returns:
3980  * D3D_OK on success
3981  * DDERR_OUTOFMEMORY if memory allocation failed
3982  * CLASS_E_NOAGGREGATION if outer_unknown != NULL
3983  *
3984  *****************************************************************************/
3985 static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material,
3986  IUnknown *outer_unknown)
3987 {
3988  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
3989  struct d3d_material *object;
3990 
3991  TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
3992 
3993  if (outer_unknown) return CLASS_E_NOAGGREGATION;
3994 
3995  object = d3d_material_create(ddraw);
3996  if (!object)
3997  {
3998  ERR("Failed to allocate material memory.\n");
3999  return DDERR_OUTOFMEMORY;
4000  }
4001 
4002  TRACE("Created material %p.\n", object);
4003  *material = &object->IDirect3DMaterial3_iface;
4004 
4005  return D3D_OK;
4006 }
4007 
4008 static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material,
4009  IUnknown *outer_unknown)
4010 {
4011  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4012  struct d3d_material *object;
4013 
4014  TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4015 
4016  object = d3d_material_create(ddraw);
4017  if (!object)
4018  {
4019  ERR("Failed to allocate material memory.\n");
4020  return DDERR_OUTOFMEMORY;
4021  }
4022 
4023  TRACE("Created material %p.\n", object);
4024  *material = &object->IDirect3DMaterial2_iface;
4025 
4026  return D3D_OK;
4027 }
4028 
4029 static HRESULT WINAPI d3d1_CreateMaterial(IDirect3D *iface, IDirect3DMaterial **material,
4030  IUnknown *outer_unknown)
4031 {
4032  struct ddraw *ddraw = impl_from_IDirect3D(iface);
4033  struct d3d_material *object;
4034 
4035  TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4036 
4037  object = d3d_material_create(ddraw);
4038  if (!object)
4039  {
4040  ERR("Failed to allocate material memory.\n");
4041  return DDERR_OUTOFMEMORY;
4042  }
4043 
4044  TRACE("Created material %p.\n", object);
4045  *material = &object->IDirect3DMaterial_iface;
4046 
4047  return D3D_OK;
4048 }
4049 
4050 /*****************************************************************************
4051  * IDirect3D3::CreateViewport
4052  *
4053  * Creates an IDirect3DViewport interface. This interface is used
4054  * by Direct3D and earlier versions for Viewport management. In Direct3D7
4055  * it has been replaced by a viewport structure and
4056  * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation
4057  * uses the IDirect3DDevice7 methods for its functionality
4058  *
4059  * Params:
4060  * Viewport: Address to store the new interface pointer
4061  * outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4062  * Must be NULL
4063  *
4064  * Returns:
4065  * D3D_OK on success
4066  * DDERR_OUTOFMEMORY if memory allocation failed
4067  * CLASS_E_NOAGGREGATION if outer_unknown != NULL
4068  *
4069  *****************************************************************************/
4070 static HRESULT WINAPI d3d3_CreateViewport(IDirect3D3 *iface, IDirect3DViewport3 **viewport,
4071  IUnknown *outer_unknown)
4072 {
4073  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4074  struct d3d_viewport *object;
4075 
4076  TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4077 
4078  if (outer_unknown) return CLASS_E_NOAGGREGATION;
4079 
4080  if (!(object = heap_alloc_zero(sizeof(*object))))
4081  {
4082  ERR("Failed to allocate viewport memory.\n");
4083  return DDERR_OUTOFMEMORY;
4084  }
4085 
4086  d3d_viewport_init(object, ddraw);
4087 
4088  TRACE("Created viewport %p.\n", object);
4089  *viewport = &object->IDirect3DViewport3_iface;
4090 
4091  return D3D_OK;
4092 }
4093 
4094 static HRESULT WINAPI d3d2_CreateViewport(IDirect3D2 *iface, IDirect3DViewport2 **viewport, IUnknown *outer_unknown)
4095 {
4096  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4097 
4098  TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4099 
4100  return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4101  outer_unknown);
4102 }
4103 
4104 static HRESULT WINAPI d3d1_CreateViewport(IDirect3D *iface, IDirect3DViewport **viewport, IUnknown *outer_unknown)
4105 {
4106  struct ddraw *ddraw = impl_from_IDirect3D(iface);
4107 
4108  TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4109 
4110  return d3d3_CreateViewport(&ddraw->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4111  outer_unknown);
4112 }
4113 
4114 /*****************************************************************************
4115  * IDirect3D3::FindDevice
4116  *
4117  * This method finds a device with the requested properties and returns a
4118  * device description
4119  *
4120  * Versions 1, 2 and 3
4121  * Params:
4122  * fds: Describes the requested device characteristics
4123  * fdr: Returns the device description
4124  *
4125  * Returns:
4126  * D3D_OK on success
4127  * DDERR_INVALIDPARAMS if no device was found
4128  *
4129  *****************************************************************************/
4131 {
4132  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4133  D3DDEVICEDESC7 desc7;
4134  D3DDEVICEDESC desc1;
4135  HRESULT hr;
4136 
4137  TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4138 
4139  if (!fds || !fdr) return DDERR_INVALIDPARAMS;
4140 
4141  if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH) || (fdr->dwSize != sizeof(D3DFINDDEVICERESULT1) &&
4142  fdr->dwSize != sizeof(D3DFINDDEVICERESULT2) && fdr->dwSize != sizeof(D3DFINDDEVICERESULT)))
4143  return DDERR_INVALIDPARAMS;
4144 
4145  if ((fds->dwFlags & D3DFDS_COLORMODEL)
4146  && fds->dcmColorModel != D3DCOLOR_RGB)
4147  {
4148  WARN("Trying to request a non-RGB D3D color model. Not supported.\n");
4149  return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
4150  }
4151 
4152  if (fds->dwFlags & D3DFDS_GUID)
4153  {
4154  TRACE("Trying to match guid %s.\n", debugstr_guid(&(fds->guid)));
4155  if (!IsEqualGUID(&IID_D3DDEVICE_WineD3D, &fds->guid)
4156  && !IsEqualGUID(&IID_IDirect3DHALDevice, &fds->guid)
4157  && !IsEqualGUID(&IID_IDirect3DRGBDevice, &fds->guid))
4158  {
4159  WARN("No match for this GUID.\n");
4160  return DDERR_NOTFOUND;
4161  }
4162  }
4163 
4164  /* Get the caps */
4165  if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &desc7)))
4166  return hr;
4167 
4168  /* Now return our own GUID */
4169  ddraw_d3dcaps1_from_7(&desc1, &desc7);
4170  fdr->guid = IID_D3DDEVICE_WineD3D;
4171 
4172  if (fdr->dwSize == sizeof(D3DFINDDEVICERESULT1))
4173  {
4175  memcpy(&fdr1->ddHwDesc, &desc1, sizeof(fdr1->ddHwDesc));
4176  memcpy(&fdr1->ddSwDesc, &desc1, sizeof(fdr1->ddSwDesc));
4177  }
4178  else if (fdr->dwSize == sizeof(D3DFINDDEVICERESULT2))
4179  {
4181  memcpy(&fdr2->ddHwDesc, &desc1, sizeof(fdr2->ddHwDesc));
4182  memcpy(&fdr2->ddSwDesc, &desc1, sizeof(fdr2->ddSwDesc));
4183  }
4184  else
4185  {
4186  fdr->ddHwDesc = desc1;
4187  fdr->ddSwDesc = desc1;
4188  }
4189 
4190  TRACE("Returning Wine's wined3d device with (undumped) capabilities.\n");
4191 
4192  return D3D_OK;
4193 }
4194 
4196 {
4197  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4198 
4199  TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4200 
4201  return d3d3_FindDevice(&ddraw->IDirect3D3_iface, fds, fdr);
4202 }
4203 
4205 {
4206  struct ddraw *ddraw = impl_from_IDirect3D(iface);
4207 
4208  TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4209 
4210  return d3d3_FindDevice(&ddraw->IDirect3D3_iface, fds, fdr);
4211 }
4212 
4213 /*****************************************************************************
4214  * IDirect3D7::CreateDevice
4215  *
4216  * Creates an IDirect3DDevice7 interface.
4217  *
4218  * Versions 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to
4219  * DirectDraw surfaces and are created with
4220  * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to
4221  * create the device object and QueryInterfaces for IDirect3DDevice
4222  *
4223  * Params:
4224  * refiid: IID of the device to create
4225  * Surface: Initial rendertarget
4226  * Device: Address to return the interface pointer
4227  *
4228  * Returns:
4229  * D3D_OK on success
4230  * DDERR_OUTOFMEMORY if memory allocation failed
4231  * DDERR_INVALIDPARAMS if a device exists already
4232  *
4233  *****************************************************************************/
4234 static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
4235  IDirectDrawSurface7 *surface, IDirect3DDevice7 **device)
4236 {
4238  struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4239  struct d3d_device *object;
4240  HRESULT hr;
4241 
4242  TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device);
4243 
4245  if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, target, (IUnknown *)surface, 7, &object, NULL)))
4246  {
4247  *device = &object->IDirect3DDevice7_iface;
4248  }
4249  else
4250  {
4251  WARN("Failed to create device, hr %#x.\n", hr);
4252  *device = NULL;
4253  }
4255 
4256  return hr;
4257 }
4258 
4259 static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid,
4260  IDirectDrawSurface4 *surface, IDirect3DDevice3 **device, IUnknown *outer_unknown)
4261 {
4262  struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface4(surface);
4263  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4264  struct d3d_device *device_impl;
4265  HRESULT hr;
4266 
4267  TRACE("iface %p, riid %s, surface %p, device %p, outer_unknown %p.\n",
4268  iface, debugstr_guid(riid), surface, device, outer_unknown);
4269 
4270  if (outer_unknown)
4271  return CLASS_E_NOAGGREGATION;
4272 
4274  if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 3, &device_impl, NULL)))
4275  {
4276  *device = &device_impl->IDirect3DDevice3_iface;
4277  }
4278  else
4279  {
4280  WARN("Failed to create device, hr %#x.\n", hr);
4281  *device = NULL;
4282  }
4284 
4285  return hr;
4286 }
4287 
4288 static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
4289  IDirectDrawSurface *surface, IDirect3DDevice2 **device)
4290 {
4291  struct ddraw_surface *surface_impl = unsafe_impl_from_IDirectDrawSurface(surface);
4292  struct ddraw *ddraw = impl_from_IDirect3D2(iface);
4293  struct d3d_device *device_impl;
4294  HRESULT hr;
4295 
4296  TRACE("iface %p, riid %s, surface %p, device %p.\n",
4297  iface, debugstr_guid(riid), surface, device);
4298 
4300  if (SUCCEEDED(hr = d3d_device_create(ddraw, riid, surface_impl, (IUnknown *)surface, 2, &device_impl, NULL)))
4301  {
4302  *device = &device_impl->IDirect3DDevice2_iface;
4303  }
4304  else
4305  {
4306  WARN("Failed to create device, hr %#x.\n", hr);
4307  *device = NULL;
4308  }
4310 
4311  return hr;
4312 }
4313 
4314 /*****************************************************************************
4315  * IDirect3D7::CreateVertexBuffer
4316  *
4317  * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7
4318  * interface.
4319  *
4320  * Versions 3 and 7
4321  *
4322  * Params:
4323  * desc: Requested Vertex buffer properties
4324  * vertex_buffer: Address to return the interface pointer at
4325  * flags: Some flags, should be 0
4326  *
4327  * Returns
4328  * D3D_OK on success
4329  * DDERR_OUTOFMEMORY if memory allocation failed
4330  * DDERR_INVALIDPARAMS if desc or vertex_buffer is NULL
4331  *
4332  *****************************************************************************/
4334  IDirect3DVertexBuffer7 **vertex_buffer, DWORD flags)
4335 {
4336  struct ddraw *ddraw = impl_from_IDirect3D7(iface);
4337  struct d3d_vertex_buffer *object;
4338  HRESULT hr;
4339 
4340  TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x.\n",
4341  iface, desc, vertex_buffer, flags);
4342 
4343  if (!vertex_buffer || !desc) return DDERR_INVALIDPARAMS;
4344 
4345  hr = d3d_vertex_buffer_create(&object, ddraw, desc);
4346  if (hr == D3D_OK)
4347  {
4348  TRACE("Created vertex buffer %p.\n", object);
4349  *vertex_buffer = &object->IDirect3DVertexBuffer7_iface;
4350  }
4351  else
4352  WARN("Failed to create vertex buffer, hr %#x.\n", hr);
4353 
4354  return hr;
4355 }
4356 
4358  IDirect3DVertexBuffer **vertex_buffer, DWORD flags, IUnknown *outer_unknown)
4359 {
4360  struct ddraw *ddraw = impl_from_IDirect3D3(iface);
4361  struct d3d_vertex_buffer *object;
4362  HRESULT hr;
4363 
4364  TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x, outer_unknown %p.\n",
4365  iface, desc, vertex_buffer, flags, outer_unknown);
4366 
4367  if (outer_unknown)
4368  return CLASS_E_NOAGGREGATION;
4369  if (!vertex_buffer || !