ReactOS  0.4.14-dev-41-g31d7680
surface.c
Go to the documentation of this file.
1 /* DirectDraw Surface Implementation
2  *
3  * Copyright (c) 1997-2000 Marcus Meissner
4  * Copyright (c) 1998-2000 Lionel Ulmer
5  * Copyright (c) 2000-2001 TransGaming Technologies Inc.
6  * Copyright (c) 2006 Stefan Dösinger
7  * Copyright (c) 2011 Ričardas Barkauskas 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 
30 
31 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface);
32 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface);
33 
34 static inline struct ddraw_surface *impl_from_IDirectDrawGammaControl(IDirectDrawGammaControl *iface)
35 {
37 }
38 
39 /* This is slow, of course. Also, in case of locks, we can't prevent other
40  * applications from drawing to the screen while we've locked the frontbuffer.
41  * We'd like to do this in wined3d instead, but for that to work wined3d needs
42  * to support windowless rendering first. */
44 {
45  struct ddraw *ddraw = surface->ddraw;
46  HDC surface_dc, screen_dc;
47  int x, y, w, h;
48  HRESULT hr;
49  BOOL ret;
50  RECT r;
51 
52  if (!rect)
53  {
54  SetRect(&r, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight);
55  rect = &r;
56  }
57 
58  x = rect->left;
59  y = rect->top;
60  w = rect->right - rect->left;
61  h = rect->bottom - rect->top;
62 
63  if (w <= 0 || h <= 0)
64  return DD_OK;
65 
67  {
68  /* Nothing to do, we control the frontbuffer, or at least the parts we
69  * care about. */
70  if (read)
71  return DD_OK;
72 
75  }
76 
77  if (FAILED(hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, &surface_dc)))
78  {
79  ERR("Failed to get surface DC, hr %#x.\n", hr);
80  return hr;
81  }
82  if (surface->palette)
83  wined3d_palette_apply_to_dc(surface->palette->wined3d_palette, surface_dc);
84 
85  if (!(screen_dc = GetDC(NULL)))
86  {
87  wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, surface_dc);
88  ERR("Failed to get screen DC.\n");
89  return E_FAIL;
90  }
91 
92  if (read)
93  ret = BitBlt(surface_dc, x, y, w, h,
94  screen_dc, x, y, SRCCOPY);
95  else
96  ret = BitBlt(screen_dc, x, y, w, h,
97  surface_dc, x, y, SRCCOPY);
98 
99  ReleaseDC(NULL, screen_dc);
100  wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, surface_dc);
101 
102  if (!ret)
103  {
104  ERR("Failed to blit to/from screen.\n");
105  return E_FAIL;
106  }
107 
108  return DD_OK;
109 }
110 
111 /*****************************************************************************
112  * IUnknown parts follow
113  *****************************************************************************/
114 
115 /*****************************************************************************
116  * IDirectDrawSurface7::QueryInterface
117  *
118  * A normal QueryInterface implementation. For QueryInterface rules
119  * see ddraw.c, IDirectDraw7::QueryInterface. This method
120  * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
121  * in all versions, the IDirectDrawGammaControl interface and it can
122  * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
123  *
124  * Params:
125  * riid: The interface id queried for
126  * obj: Address to write the pointer to
127  *
128  * Returns:
129  * S_OK on success
130  * E_NOINTERFACE if the requested interface wasn't found
131  *
132  *****************************************************************************/
134 {
136 
137  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
138 
139  /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
140  *obj = NULL;
141 
142  if(!riid)
143  return DDERR_INVALIDPARAMS;
144 
145  if (IsEqualGUID(riid, &IID_IDirectDrawSurface7))
146  {
147  IDirectDrawSurface7_AddRef(iface);
148  *obj = iface;
149  TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj);
150  return S_OK;
151  }
152 
153  if (IsEqualGUID(riid, &IID_IDirectDrawSurface4))
154  {
155  IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface);
156  *obj = &This->IDirectDrawSurface4_iface;
157  TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj);
158  return S_OK;
159  }
160 
161  if (IsEqualGUID(riid, &IID_IDirectDrawSurface3))
162  {
163  IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
164  *obj = &This->IDirectDrawSurface3_iface;
165  TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
166  return S_OK;
167  }
168 
169  if (IsEqualGUID(riid, &IID_IDirectDrawSurface2))
170  {
171  IDirectDrawSurface2_AddRef(&This->IDirectDrawSurface2_iface);
172  *obj = &This->IDirectDrawSurface2_iface;
173  TRACE("(%p) returning IDirectDrawSurface2 interface at %p\n", This, *obj);
174  return S_OK;
175  }
176 
177  if (IsEqualGUID(riid, &IID_IDirectDrawSurface)
179  {
180  IDirectDrawSurface_AddRef(&This->IDirectDrawSurface_iface);
181  *obj = &This->IDirectDrawSurface_iface;
182  TRACE("(%p) returning IDirectDrawSurface interface at %p\n", This, *obj);
183  return S_OK;
184  }
185 
186  if (IsEqualGUID(riid, &IID_IDirectDrawGammaControl))
187  {
188  IDirectDrawGammaControl_AddRef(&This->IDirectDrawGammaControl_iface);
189  *obj = &This->IDirectDrawGammaControl_iface;
190  TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj);
191  return S_OK;
192  }
193 
194  if (IsEqualGUID(riid, &IID_IDirectDrawColorControl))
195  {
196  WARN("Color control not implemented.\n");
197  *obj = NULL;
198  return E_NOINTERFACE;
199  }
200 
201  if (This->version != 7)
202  {
204  || IsEqualGUID(riid, &IID_IDirect3DHALDevice)
205  || IsEqualGUID(riid, &IID_IDirect3DRGBDevice))
206  {
208  if (!This->device1)
209  {
210  HRESULT hr;
211 
212  if (FAILED(hr = d3d_device_create(This->ddraw, riid, This, (IUnknown *)&This->IDirectDrawSurface_iface,
213  1, &This->device1, (IUnknown *)&This->IDirectDrawSurface_iface)))
214  {
215  This->device1 = NULL;
217  WARN("Failed to create device, hr %#x.\n", hr);
218  return hr;
219  }
220  }
222 
223  IDirect3DDevice_AddRef(&This->device1->IDirect3DDevice_iface);
224  *obj = &This->device1->IDirect3DDevice_iface;
225  return S_OK;
226  }
227 
228  if (IsEqualGUID(&IID_IDirect3DTexture2, riid))
229  {
230  IDirect3DTexture2_AddRef(&This->IDirect3DTexture2_iface);
231  *obj = &This->IDirect3DTexture2_iface;
232  return S_OK;
233  }
234 
235  if (IsEqualGUID( &IID_IDirect3DTexture, riid ))
236  {
237  IDirect3DTexture2_AddRef(&This->IDirect3DTexture_iface);
238  *obj = &This->IDirect3DTexture_iface;
239  return S_OK;
240  }
241  }
242 
243  WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
244 
245  if (This->version != 7)
246  return E_INVALIDARG;
247 
248  return E_NOINTERFACE;
249 }
250 
251 static HRESULT WINAPI ddraw_surface4_QueryInterface(IDirectDrawSurface4 *iface, REFIID riid, void **object)
252 {
253  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
254 
255  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
256 
258 }
259 
260 static HRESULT WINAPI ddraw_surface3_QueryInterface(IDirectDrawSurface3 *iface, REFIID riid, void **object)
261 {
262  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
263 
264  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
265 
267 }
268 
269 static HRESULT WINAPI ddraw_surface2_QueryInterface(IDirectDrawSurface2 *iface, REFIID riid, void **object)
270 {
271  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
272 
273  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
274 
276 }
277 
278 static HRESULT WINAPI ddraw_surface1_QueryInterface(IDirectDrawSurface *iface, REFIID riid, void **object)
279 {
280  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
281 
282  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
283 
285 }
286 
287 static HRESULT WINAPI ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl *iface,
288  REFIID riid, void **object)
289 {
290  struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
291 
292  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
293 
295 }
296 
297 static HRESULT WINAPI d3d_texture2_QueryInterface(IDirect3DTexture2 *iface, REFIID riid, void **object)
298 {
299  struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
300 
301  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
302 
304 }
305 
306 static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFIID riid, void **object)
307 {
308  struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
309 
310  TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
311 
313 }
314 
315 static void ddraw_surface_add_iface(struct ddraw_surface *surface)
316 {
318  TRACE("%p increasing iface count to %u.\n", surface, iface_count);
319 
320  if (iface_count == 1)
321  {
322  if (surface->ifaceToRelease)
323  IUnknown_AddRef(surface->ifaceToRelease);
325  if (surface->wined3d_rtv)
329  }
330 }
331 
332 /*****************************************************************************
333  * IDirectDrawSurface7::AddRef
334  *
335  * A normal addref implementation
336  *
337  * Returns:
338  * The new refcount
339  *
340  *****************************************************************************/
342 {
344  ULONG refcount = InterlockedIncrement(&This->ref7);
345 
346  TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
347 
348  if (refcount == 1)
349  {
351  }
352 
353  return refcount;
354 }
355 
356 static ULONG WINAPI ddraw_surface4_AddRef(IDirectDrawSurface4 *iface)
357 {
359  ULONG refcount = InterlockedIncrement(&This->ref4);
360 
361  TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
362 
363  if (refcount == 1)
364  {
366  }
367 
368  return refcount;
369 }
370 
371 static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface)
372 {
374  ULONG refcount = InterlockedIncrement(&This->ref3);
375 
376  TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
377 
378  if (refcount == 1)
379  {
381  }
382 
383  return refcount;
384 }
385 
386 static ULONG WINAPI ddraw_surface2_AddRef(IDirectDrawSurface2 *iface)
387 {
389  ULONG refcount = InterlockedIncrement(&This->ref2);
390 
391  TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
392 
393  if (refcount == 1)
394  {
396  }
397 
398  return refcount;
399 }
400 
401 static ULONG WINAPI ddraw_surface1_AddRef(IDirectDrawSurface *iface)
402 {
404  ULONG refcount = InterlockedIncrement(&This->ref1);
405 
406  TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
407 
408  if (refcount == 1)
409  {
411  }
412 
413  return refcount;
414 }
415 
416 static ULONG WINAPI ddraw_gamma_control_AddRef(IDirectDrawGammaControl *iface)
417 {
419  ULONG refcount = InterlockedIncrement(&This->gamma_count);
420 
421  TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
422 
423  if (refcount == 1)
424  {
426  }
427 
428  return refcount;
429 }
430 
431 static ULONG WINAPI d3d_texture2_AddRef(IDirect3DTexture2 *iface)
432 {
433  struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
434 
435  TRACE("iface %p.\n", iface);
436 
437  return IUnknown_AddRef(surface->texture_outer);
438 }
439 
440 static ULONG WINAPI d3d_texture1_AddRef(IDirect3DTexture *iface)
441 {
442  struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
443 
444  TRACE("iface %p.\n", iface);
445 
446  return IUnknown_AddRef(surface->texture_outer);
447 }
448 
449 static HRESULT ddraw_surface_set_palette(struct ddraw_surface *surface, IDirectDrawPalette *palette)
450 {
452  struct ddraw_palette *prev;
453 
454  TRACE("iface %p, palette %p.\n", surface, palette);
455 
456  if (palette_impl && palette_impl->flags & DDPCAPS_ALPHA
457  && !(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
458  {
459  WARN("Alpha palette set on non-texture surface, returning DDERR_INVALIDSURFACETYPE.\n");
461  }
462 
465 
467 
468  prev = surface->palette;
470  {
471  if (prev)
472  prev->flags &= ~DDPCAPS_PRIMARYSURFACE;
473  if (palette_impl)
474  palette_impl->flags |= DDPCAPS_PRIMARYSURFACE;
475  wined3d_swapchain_set_palette(surface->ddraw->wined3d_swapchain,
476  palette_impl ? palette_impl->wined3d_palette : NULL);
478  }
479  if (palette_impl)
480  IDirectDrawPalette_AddRef(&palette_impl->IDirectDrawPalette_iface);
481  if (prev)
482  IDirectDrawPalette_Release(&prev->IDirectDrawPalette_iface);
483  surface->palette = palette_impl;
484 
486 
487  return DD_OK;
488 }
489 
490 static void ddraw_surface_cleanup(struct ddraw_surface *surface)
491 {
492  struct ddraw_surface *surf;
493  UINT i;
494 
495  TRACE("surface %p.\n", surface);
496 
497  /* The refcount test shows that the palette is detached when the surface
498  * is destroyed. */
500 
501  /* Loop through all complex attached surfaces and destroy them.
502  *
503  * Yet again, only the root can have more than one complexly attached
504  * surface, all the others have a total of one. */
505  for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
506  {
507  if (!surface->complex_array[i])
508  break;
509 
510  surf = surface->complex_array[i];
511  surface->complex_array[i] = NULL;
512  if (!surf->is_complex_root)
513  ddraw_surface_cleanup(surf);
514  }
515 
516  if (surface->device1)
517  IUnknown_Release(&surface->device1->IUnknown_inner);
518 
519  if (surface->iface_count > 1)
520  {
521  /* This can happen when a complex surface is destroyed, because the
522  * 2nd surface was addref()ed when the app called
523  * GetAttachedSurface(). */
524  WARN("Destroying surface %p with refcounts 7: %u 4: %u 3: %u 2: %u 1: %u.\n",
525  surface, surface->ref7, surface->ref4, surface->ref3, surface->ref2, surface->ref1);
526  }
527 
528  if (surface->wined3d_rtv)
531 }
532 
534 {
536 
537  /* Prevent the surface from being destroyed if it's still attached to
538  * another surface. It will be destroyed when the root is destroyed. */
539  if (This->iface_count == 1 && This->attached_iface)
540  IUnknown_AddRef(This->attached_iface);
541  iface_count = InterlockedDecrement(&This->iface_count);
542 
543  TRACE("%p decreasing iface count to %u.\n", This, iface_count);
544 
545  if (iface_count == 0)
546  {
547  struct ddraw_texture *texture = wined3d_texture_get_parent(This->wined3d_texture);
548  struct wined3d_device *wined3d_device = texture->wined3d_device;
549  IUnknown *release_iface = This->ifaceToRelease;
550 
551  /* Complex attached surfaces are destroyed implicitly when the root is released */
553  if(!This->is_complex_root)
554  {
555  WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
557  return iface_count;
558  }
561 
562  if (release_iface)
563  IUnknown_Release(release_iface);
564  /* Release the device only after anything that may reference it (the
565  * wined3d texture and rendertarget view in particular) is released. */
567  }
568 
569  return iface_count;
570 }
571 
572 /*****************************************************************************
573  * IDirectDrawSurface7::Release
574  *
575  * Reduces the surface's refcount by 1. If the refcount falls to 0, the
576  * surface is destroyed.
577  *
578  * Destroying the surface is a bit tricky. For the connection between
579  * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
580  * It has a nice graph explaining the connection.
581  *
582  * What happens here is basically this:
583  * When a surface is destroyed, its WineD3DSurface is released,
584  * and the refcount of the DirectDraw interface is reduced by 1. If it has
585  * complex surfaces attached to it, then these surfaces are destroyed too,
586  * regardless of their refcount. If any surface being destroyed has another
587  * surface attached to it (with a "soft" attachment, not complex), then
588  * this surface is detached with DeleteAttachedSurface.
589  *
590  * When the surface is a texture, the WineD3DTexture is released.
591  * If the surface is the Direct3D render target, then the D3D
592  * capabilities of the WineD3DDevice are uninitialized, which causes the
593  * swapchain to be released.
594  *
595  * When a complex sublevel falls to ref zero, then this is ignored.
596  *
597  * Returns:
598  * The new refcount
599  *
600  *****************************************************************************/
602 {
604  ULONG refcount = InterlockedDecrement(&This->ref7);
605 
606  TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
607 
608  if (refcount == 0)
609  {
611  }
612 
613  return refcount;
614 }
615 
616 static ULONG WINAPI ddraw_surface4_Release(IDirectDrawSurface4 *iface)
617 {
619  ULONG refcount = InterlockedDecrement(&This->ref4);
620 
621  TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
622 
623  if (refcount == 0)
624  {
626  }
627 
628  return refcount;
629 }
630 
631 static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface)
632 {
634  ULONG refcount = InterlockedDecrement(&This->ref3);
635 
636  TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
637 
638  if (refcount == 0)
639  {
641  }
642 
643  return refcount;
644 }
645 
646 static ULONG WINAPI ddraw_surface2_Release(IDirectDrawSurface2 *iface)
647 {
649  ULONG refcount = InterlockedDecrement(&This->ref2);
650 
651  TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
652 
653  if (refcount == 0)
654  {
656  }
657 
658  return refcount;
659 }
660 
661 static ULONG WINAPI ddraw_surface1_Release(IDirectDrawSurface *iface)
662 {
664  ULONG refcount = InterlockedDecrement(&This->ref1);
665 
666  TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
667 
668  if (refcount == 0)
669  {
671  }
672 
673  return refcount;
674 }
675 
676 static ULONG WINAPI ddraw_gamma_control_Release(IDirectDrawGammaControl *iface)
677 {
679  ULONG refcount = InterlockedDecrement(&This->gamma_count);
680 
681  TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
682 
683  if (refcount == 0)
684  {
686  }
687 
688  return refcount;
689 }
690 
691 static ULONG WINAPI d3d_texture2_Release(IDirect3DTexture2 *iface)
692 {
693  struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
694 
695  TRACE("iface %p.\n", iface);
696 
697  return IUnknown_Release(surface->texture_outer);
698 }
699 
700 static ULONG WINAPI d3d_texture1_Release(IDirect3DTexture *iface)
701 {
702  struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
703 
704  TRACE("iface %p.\n", iface);
705 
706  return IUnknown_Release(surface->texture_outer);
707 }
708 
709 /*****************************************************************************
710  * IDirectDrawSurface7::GetAttachedSurface
711  *
712  * Returns an attached surface with the requested caps. Surface attachment
713  * and complex surfaces are not clearly described by the MSDN or sdk,
714  * so this method is tricky and likely to contain problems.
715  * This implementation searches the complex list first, then the
716  * attachment chain.
717  *
718  * The chains are searched from This down to the last surface in the chain,
719  * not from the first element in the chain. The first surface found is
720  * returned. The MSDN says that this method fails if more than one surface
721  * matches the caps, but it is not sure if that is right. The attachment
722  * structure may not even allow two matching surfaces.
723  *
724  * The found surface is AddRef-ed before it is returned.
725  *
726  * Params:
727  * Caps: Pointer to a DDCAPS2 structure describing the caps asked for
728  * Surface: Address to store the found surface
729  *
730  * Returns:
731  * DD_OK on success
732  * DDERR_INVALIDPARAMS if Caps or Surface is NULL
733  * DDERR_NOTFOUND if no surface was found
734  *
735  *****************************************************************************/
737  DDSCAPS2 *Caps, IDirectDrawSurface7 **Surface)
738 {
740  struct ddraw_surface *surf;
741  DDSCAPS2 our_caps;
742  int i;
743 
744  TRACE("iface %p, caps %p, attachment %p.\n", iface, Caps, Surface);
745 
747 
748  if(This->version < 7)
749  {
750  /* Earlier dx apps put garbage into these members, clear them */
751  our_caps.dwCaps = Caps->dwCaps;
752  our_caps.dwCaps2 = 0;
753  our_caps.dwCaps3 = 0;
754  our_caps.u1.dwCaps4 = 0;
755  }
756  else
757  {
758  our_caps = *Caps;
759  }
760 
761  TRACE("(%p): Looking for caps: %x,%x,%x,%x\n", This, our_caps.dwCaps, our_caps.dwCaps2, our_caps.dwCaps3, our_caps.u1.dwCaps4); /* FIXME: Better debugging */
762 
763  for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
764  {
765  surf = This->complex_array[i];
766  if(!surf) break;
767 
768  TRACE("Surface: (%p) caps: %#x, %#x, %#x, %#x.\n", surf,
772  surf->surface_desc.ddsCaps.u1.dwCaps4);
773 
774  if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
775  ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
776 
777  /* MSDN: "This method fails if more than one surface is attached
778  * that matches the capabilities requested."
779  *
780  * Not sure how to test this.
781  */
782 
783  TRACE("(%p): Returning surface %p\n", This, surf);
784  *Surface = &surf->IDirectDrawSurface7_iface;
785  ddraw_surface7_AddRef(*Surface);
787 
788  return DD_OK;
789  }
790  }
791 
792  /* Next, look at the attachment chain */
793  surf = This;
794 
795  while( (surf = surf->next_attached) )
796  {
797  TRACE("Surface: (%p) caps: %#x, %#x, %#x, %#x.\n", surf,
801  surf->surface_desc.ddsCaps.u1.dwCaps4);
802 
803  if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
804  ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
805 
806  TRACE("(%p): Returning surface %p\n", This, surf);
807  *Surface = &surf->IDirectDrawSurface7_iface;
808  ddraw_surface7_AddRef(*Surface);
810  return DD_OK;
811  }
812  }
813 
814  TRACE("(%p) Didn't find a valid surface\n", This);
815 
817 
818  *Surface = NULL;
819  return DDERR_NOTFOUND;
820 }
821 
822 static HRESULT WINAPI ddraw_surface4_GetAttachedSurface(IDirectDrawSurface4 *iface,
823  DDSCAPS2 *caps, IDirectDrawSurface4 **attachment)
824 {
825  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
826  struct ddraw_surface *attachment_impl;
827  IDirectDrawSurface7 *attachment7;
828  HRESULT hr;
829 
830  TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
831 
833  caps, &attachment7);
834  if (FAILED(hr))
835  {
836  *attachment = NULL;
837  return hr;
838  }
839  attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
840  *attachment = &attachment_impl->IDirectDrawSurface4_iface;
842  ddraw_surface7_Release(attachment7);
843 
844  return hr;
845 }
846 
847 static HRESULT WINAPI ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3 *iface,
848  DDSCAPS *caps, IDirectDrawSurface3 **attachment)
849 {
850  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
851  struct ddraw_surface *attachment_impl;
852  IDirectDrawSurface7 *attachment7;
853  DDSCAPS2 caps2;
854  HRESULT hr;
855 
856  TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
857 
858  caps2.dwCaps = caps->dwCaps;
859  caps2.dwCaps2 = 0;
860  caps2.dwCaps3 = 0;
861  caps2.u1.dwCaps4 = 0;
862 
864  &caps2, &attachment7);
865  if (FAILED(hr))
866  {
867  *attachment = NULL;
868  return hr;
869  }
870  attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
871  *attachment = &attachment_impl->IDirectDrawSurface3_iface;
873  ddraw_surface7_Release(attachment7);
874 
875  return hr;
876 }
877 
878 static HRESULT WINAPI ddraw_surface2_GetAttachedSurface(IDirectDrawSurface2 *iface,
879  DDSCAPS *caps, IDirectDrawSurface2 **attachment)
880 {
881  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
882  struct ddraw_surface *attachment_impl;
883  IDirectDrawSurface7 *attachment7;
884  DDSCAPS2 caps2;
885  HRESULT hr;
886 
887  TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
888 
889  caps2.dwCaps = caps->dwCaps;
890  caps2.dwCaps2 = 0;
891  caps2.dwCaps3 = 0;
892  caps2.u1.dwCaps4 = 0;
893 
895  &caps2, &attachment7);
896  if (FAILED(hr))
897  {
898  *attachment = NULL;
899  return hr;
900  }
901  attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
902  *attachment = &attachment_impl->IDirectDrawSurface2_iface;
904  ddraw_surface7_Release(attachment7);
905 
906  return hr;
907 }
908 
909 static HRESULT WINAPI ddraw_surface1_GetAttachedSurface(IDirectDrawSurface *iface,
910  DDSCAPS *caps, IDirectDrawSurface **attachment)
911 {
912  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
913  struct ddraw_surface *attachment_impl;
914  IDirectDrawSurface7 *attachment7;
915  DDSCAPS2 caps2;
916  HRESULT hr;
917 
918  TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
919 
920  caps2.dwCaps = caps->dwCaps;
921  caps2.dwCaps2 = 0;
922  caps2.dwCaps3 = 0;
923  caps2.u1.dwCaps4 = 0;
924 
926  &caps2, &attachment7);
927  if (FAILED(hr))
928  {
929  *attachment = NULL;
930  return hr;
931  }
932  attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
933  *attachment = &attachment_impl->IDirectDrawSurface_iface;
935  ddraw_surface7_Release(attachment7);
936 
937  return hr;
938 }
939 
940 /*****************************************************************************
941  * IDirectDrawSurface7::Lock
942  *
943  * Locks the surface and returns a pointer to the surface's memory
944  *
945  * Params:
946  * Rect: Rectangle to lock. If NULL, the whole surface is locked
947  * DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
948  * Flags: Locking flags, e.g Read only or write only
949  * h: An event handle that's not used and must be NULL
950  *
951  * Returns:
952  * DD_OK on success
953  * DDERR_INVALIDPARAMS if DDSD is NULL
954  *
955  *****************************************************************************/
956 static HRESULT surface_lock(struct ddraw_surface *surface,
957  RECT *rect, DDSURFACEDESC2 *surface_desc, unsigned int surface_desc_size,
958  DWORD flags, HANDLE h)
959 {
960  struct wined3d_map_desc map_desc;
961  struct wined3d_box box;
962  HRESULT hr = DD_OK;
963 
964  TRACE("surface %p, rect %s, surface_desc %p, surface_desc_size %u, flags %#x, h %p.\n",
965  surface, wine_dbgstr_rect(rect), surface_desc, surface_desc_size, flags, h);
966 
967  /* surface->surface_desc.dwWidth and dwHeight are changeable, thus lock */
969 
970  /* Should I check for the handle to be NULL?
971  *
972  * The DDLOCK flags and the D3DLOCK flags are equal
973  * for the supported values. The others are ignored by WineD3D
974  */
975 
976  /* Windows zeroes this if the rect is invalid */
977  surface_desc->lpSurface = NULL;
978 
979  if (rect)
980  {
981  if ((rect->left < 0) || (rect->top < 0)
982  || (rect->left > rect->right) || (rect->right > surface->surface_desc.dwWidth)
983  || (rect->top > rect->bottom) || (rect->bottom > surface->surface_desc.dwHeight))
984  {
985  WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
987  return DDERR_INVALIDPARAMS;
988  }
989  wined3d_box_set(&box, rect->left, rect->top, rect->right, rect->bottom, 0, 1);
990  }
991 
994  if (SUCCEEDED(hr))
996  surface->sub_resource_idx, &map_desc, rect ? &box : NULL,
998  if (FAILED(hr))
999  {
1001  switch(hr)
1002  {
1003  /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
1004  * specific error. But since wined3d returns that error in this only occasion,
1005  * keep d3d8 and d3d9 free from the return value override. There are many different
1006  * places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it is much easier
1007  * to do it in one place in ddraw.
1008  */
1010  default: return hr;
1011  }
1012  }
1013 
1015  {
1016  if (flags & DDLOCK_READONLY)
1017  SetRectEmpty(&surface->ddraw->primary_lock);
1018  else if (rect)
1019  surface->ddraw->primary_lock = *rect;
1020  else
1021  SetRect(&surface->ddraw->primary_lock, 0, 0, surface->surface_desc.dwWidth, surface->surface_desc.dwHeight);
1022  }
1023 
1024  /* Windows does not set DDSD_LPSURFACE on locked surfaces. */
1025  DD_STRUCT_COPY_BYSIZE_(surface_desc, &surface->surface_desc, surface_desc_size, surface->surface_desc.dwSize);
1026  surface_desc->lpSurface = map_desc.data;
1027 
1028  TRACE("locked surface returning description :\n");
1029  if (TRACE_ON(ddraw))
1030  DDRAW_dump_surface_desc(surface_desc);
1031 
1033 
1034  return DD_OK;
1035 }
1036 
1038  const DDSURFACEDESC *desc, unsigned int *size)
1039 {
1040  if (!desc)
1041  return FALSE;
1042 
1043  if (desc->dwSize == sizeof(DDSURFACEDESC) || desc->dwSize == sizeof(DDSURFACEDESC2))
1044  {
1045  *size = desc->dwSize;
1046  return TRUE;
1047  }
1048 
1049  if (surface->version == 7
1052  {
1053  if (desc->dwSize >= sizeof(DDSURFACEDESC2))
1054  *size = sizeof(DDSURFACEDESC2);
1055  else
1056  *size = sizeof(DDSURFACEDESC);
1057  return TRUE;
1058  }
1059 
1060  WARN("Invalid structure size %u.\n", desc->dwSize);
1061  return FALSE;
1062 }
1063 
1065  RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
1066 {
1067  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1068  unsigned int surface_desc_size;
1069 
1070  TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1072 
1073  if (!surface_validate_lock_desc(surface, (DDSURFACEDESC *)surface_desc, &surface_desc_size))
1074  return DDERR_INVALIDPARAMS;
1075 
1076  return surface_lock(surface, rect, surface_desc, surface_desc_size, flags, h);
1077 }
1078 
1079 static HRESULT WINAPI ddraw_surface4_Lock(IDirectDrawSurface4 *iface, RECT *rect,
1081 {
1082  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1083  unsigned int surface_desc_size;
1084 
1085  TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1087 
1088  if (!surface_validate_lock_desc(surface, (DDSURFACEDESC *)surface_desc, &surface_desc_size))
1089  return DDERR_INVALIDPARAMS;
1090 
1091  return surface_lock(surface, rect, surface_desc, surface_desc_size, flags, h);
1092 }
1093 
1094 static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect,
1096 {
1097  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1098  unsigned int surface_desc_size;
1099  DDSURFACEDESC2 surface_desc2;
1100  HRESULT hr;
1101 
1102  TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1104 
1105  if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size))
1106  return DDERR_INVALIDPARAMS;
1107 
1108  surface_desc2.dwSize = surface_desc->dwSize;
1109  surface_desc2.dwFlags = 0;
1110  hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h);
1111  DDSD2_to_DDSD(&surface_desc2, surface_desc);
1112  surface_desc->dwSize = surface_desc2.dwSize;
1113  return hr;
1114 }
1115 
1116 static HRESULT WINAPI ddraw_surface2_Lock(IDirectDrawSurface2 *iface, RECT *rect,
1118 {
1119  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1120  unsigned int surface_desc_size;
1121  DDSURFACEDESC2 surface_desc2;
1122  HRESULT hr;
1123 
1124  TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1126 
1127  if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size))
1128  return DDERR_INVALIDPARAMS;
1129 
1130  surface_desc2.dwSize = surface_desc->dwSize;
1131  surface_desc2.dwFlags = 0;
1132  hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h);
1133  DDSD2_to_DDSD(&surface_desc2, surface_desc);
1134  surface_desc->dwSize = surface_desc2.dwSize;
1135  return hr;
1136 }
1137 
1138 static HRESULT WINAPI ddraw_surface1_Lock(IDirectDrawSurface *iface, RECT *rect,
1140 {
1141  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1142  unsigned int surface_desc_size;
1143  DDSURFACEDESC2 surface_desc2;
1144  HRESULT hr;
1145 
1146  TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1148 
1149  if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size))
1150  return DDERR_INVALIDPARAMS;
1151 
1152  surface_desc2.dwSize = surface_desc->dwSize;
1153  surface_desc2.dwFlags = 0;
1154  hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h);
1155  DDSD2_to_DDSD(&surface_desc2, surface_desc);
1156  surface_desc->dwSize = surface_desc2.dwSize;
1157  return hr;
1158 }
1159 
1160 /*****************************************************************************
1161  * IDirectDrawSurface7::Unlock
1162  *
1163  * Unlocks an locked surface
1164  *
1165  * Params:
1166  * Rect: Not used by this implementation
1167  *
1168  * Returns:
1169  * D3D_OK on success, error code otherwise.
1170  *
1171  *****************************************************************************/
1173 {
1174  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1175  HRESULT hr;
1176 
1177  TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(pRect));
1178 
1182  hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE);
1184 
1185  return hr;
1186 }
1187 
1188 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Unlock(IDirectDrawSurface4 *iface, RECT *pRect)
1189 {
1190  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1191 
1192  TRACE("iface %p, rect %p.\n", iface, pRect);
1193 
1194  return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, pRect);
1195 }
1196 
1197 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Unlock(IDirectDrawSurface3 *iface, void *data)
1198 {
1199  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1200 
1201  TRACE("iface %p, data %p.\n", iface, data);
1202 
1203  /* data might not be the LPRECT of later versions, so drop it. */
1205 }
1206 
1207 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Unlock(IDirectDrawSurface2 *iface, void *data)
1208 {
1209  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1210 
1211  TRACE("iface %p, data %p.\n", iface, data);
1212 
1213  /* data might not be the LPRECT of later versions, so drop it. */
1215 }
1216 
1217 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Unlock(IDirectDrawSurface *iface, void *data)
1218 {
1219  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1220 
1221  TRACE("iface %p, data %p.\n", iface, data);
1222 
1223  /* data might not be the LPRECT of later versions, so drop it. */
1225 }
1226 
1229 {
1230  struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
1232  struct wined3d_rendertarget_view *tmp_rtv, *src_rtv, *rtv;
1233  struct ddraw_texture *ddraw_texture, *prev_ddraw_texture;
1234  DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
1235  struct wined3d_texture *texture;
1237  HRESULT hr;
1238 
1239  TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1240 
1241  if (src == iface || !(dst_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)))
1242  return DDERR_NOTFLIPPABLE;
1243 
1244  if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
1245  return DDERR_SURFACELOST;
1246 
1248 
1250  && !(dst_impl->ddraw->cooperative_level & DDSCL_EXCLUSIVE))
1251  {
1252  WARN("Not in exclusive mode.\n");
1254  return DDERR_NOEXCLUSIVEMODE;
1255  }
1256 
1257  tmp_rtv = ddraw_surface_get_rendertarget_view(dst_impl);
1258  if (dst_impl->sub_resource_idx)
1259  ERR("Invalid sub-resource index %u on surface %p.\n", dst_impl->sub_resource_idx, dst_impl);
1260  texture = dst_impl->wined3d_texture;
1261  rtv = wined3d_device_get_rendertarget_view(dst_impl->ddraw->wined3d_device, 0);
1263 
1264  if (src_impl)
1265  {
1266  for (current = iface; current != src;)
1267  {
1269  {
1270  WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
1272  return DDERR_NOTFLIPPABLE;
1273  }
1275  if (current == iface)
1276  {
1277  WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
1279  return DDERR_NOTFLIPPABLE;
1280  }
1281  }
1282 
1283  src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
1284  if (rtv == dst_impl->wined3d_rtv)
1285  wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
1286  wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
1287  dst_impl->wined3d_rtv = src_rtv;
1289  prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
1291  if (src_impl->sub_resource_idx)
1292  ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl);
1293  dst_impl->wined3d_texture = src_impl->wined3d_texture;
1294  ddraw_texture = prev_ddraw_texture;
1295  }
1296  else
1297  {
1298  for (current = iface;;)
1299  {
1301  {
1302  ERR("Can't find a flip target\n");
1304  return DDERR_NOTFLIPPABLE; /* Unchecked */
1305  }
1307  if (current == iface)
1308  {
1309  dst_impl = impl_from_IDirectDrawSurface7(iface);
1310  break;
1311  }
1312 
1314  src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
1315  if (rtv == dst_impl->wined3d_rtv)
1316  wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
1317  wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
1318  dst_impl->wined3d_rtv = src_rtv;
1320  prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
1322  ddraw_texture = prev_ddraw_texture;
1323  if (src_impl->sub_resource_idx)
1324  ERR("Invalid sub-resource index %u on surface %p.\n", src_impl->sub_resource_idx, src_impl);
1325  dst_impl->wined3d_texture = src_impl->wined3d_texture;
1326  dst_impl = src_impl;
1327  }
1328  }
1329 
1330  /* We don't have to worry about potential texture bindings, since
1331  * flippable surfaces can never be textures. */
1332  if (rtv == src_impl->wined3d_rtv)
1333  wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, tmp_rtv, FALSE);
1334  wined3d_rendertarget_view_set_parent(tmp_rtv, src_impl);
1335  src_impl->wined3d_rtv = tmp_rtv;
1338  src_impl->wined3d_texture = texture;
1339 
1340  if (flags)
1341  {
1342  static UINT once;
1343  if (!once++)
1344  FIXME("Ignoring flags %#x.\n", flags);
1345  else
1346  WARN("Ignoring flags %#x.\n", flags);
1347  }
1348 
1351  else
1352  hr = DD_OK;
1353 
1355 
1356  return hr;
1357 }
1358 
1359 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Flip(IDirectDrawSurface4 *iface,
1360  IDirectDrawSurface4 *src, DWORD flags)
1361 {
1362  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1364 
1365  TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1366 
1368  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags);
1369 }
1370 
1371 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Flip(IDirectDrawSurface3 *iface,
1372  IDirectDrawSurface3 *src, DWORD flags)
1373 {
1374  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1376 
1377  TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1378 
1380  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags);
1381 }
1382 
1383 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Flip(IDirectDrawSurface2 *iface,
1384  IDirectDrawSurface2 *src, DWORD flags)
1385 {
1386  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1388 
1389  TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1390 
1392  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags);
1393 }
1394 
1395 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *iface,
1396  IDirectDrawSurface *src, DWORD flags)
1397 {
1398  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1400 
1401  TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1402 
1404  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags);
1405 }
1406 
1407 static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT *dst_rect,
1408  struct ddraw_surface *src_surface, const RECT *src_rect, DWORD flags, DWORD fill_colour,
1410 {
1411  struct wined3d_device *wined3d_device = dst_surface->ddraw->wined3d_device;
1412  struct wined3d_color colour;
1413  DWORD wined3d_flags;
1414 
1415  if (flags & DDBLT_COLORFILL)
1416  {
1418  dst_surface->palette, fill_colour, &colour))
1419  return DDERR_INVALIDPARAMS;
1420 
1423  dst_rect, WINED3DCLEAR_TARGET, &colour, 0.0f, 0);
1424  }
1425 
1426  if (flags & DDBLT_DEPTHFILL)
1427  {
1429  dst_surface->palette, fill_colour, &colour))
1430  return DDERR_INVALIDPARAMS;
1431 
1434  dst_rect, WINED3DCLEAR_ZBUFFER, NULL, colour.r, 0);
1435  }
1436 
1437  wined3d_flags = flags & ~DDBLT_ASYNC;
1438  if (wined3d_flags & ~WINED3D_BLT_MASK)
1439  {
1440  FIXME("Unhandled flags %#x.\n", flags);
1441  return E_NOTIMPL;
1442  }
1443 
1444  if (!(flags & DDBLT_ASYNC))
1445  wined3d_flags |= WINED3D_BLT_SYNCHRONOUS;
1446 
1447  return wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, dst_rect,
1448  src_surface->wined3d_texture, src_surface->sub_resource_idx, src_rect, wined3d_flags, fx, filter);
1449 }
1450 
1451 static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, const RECT *dst_rect_in,
1452  struct ddraw_surface *src_surface, const RECT *src_rect_in, DWORD flags, DWORD fill_colour,
1454 {
1455  RECT src_rect, dst_rect;
1456  float scale_x, scale_y;
1457  const RECT *clip_rect;
1458  UINT clip_list_size;
1459  RGNDATA *clip_list;
1460  HRESULT hr = DD_OK;
1461  UINT i;
1462 
1463  if (!dst_rect_in)
1464  SetRect(&dst_rect, 0, 0, dst_surface->surface_desc.dwWidth,
1465  dst_surface->surface_desc.dwHeight);
1466  else
1467  dst_rect = *dst_rect_in;
1468 
1469  if (IsRectEmpty(&dst_rect))
1470  return DDERR_INVALIDRECT;
1471 
1472  if (src_surface)
1473  {
1474  if (!src_rect_in)
1475  SetRect(&src_rect, 0, 0, src_surface->surface_desc.dwWidth,
1476  src_surface->surface_desc.dwHeight);
1477  else
1478  src_rect = *src_rect_in;
1479 
1480  if (IsRectEmpty(&src_rect))
1481  return DDERR_INVALIDRECT;
1482  }
1483  else
1484  {
1485  SetRectEmpty(&src_rect);
1486  }
1487 
1488  if (!dst_surface->clipper)
1489  {
1490  if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1491  hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE);
1492  if (SUCCEEDED(hr))
1493  hr = ddraw_surface_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fill_colour, fx, filter);
1494  if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
1495  hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE);
1496 
1497  return hr;
1498  }
1499 
1500  scale_x = (float)(src_rect.right - src_rect.left) / (float)(dst_rect.right - dst_rect.left);
1501  scale_y = (float)(src_rect.bottom - src_rect.top) / (float)(dst_rect.bottom - dst_rect.top);
1502 
1503  if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
1504  &dst_rect, NULL, &clip_list_size)))
1505  {
1506  WARN("Failed to get clip list size, hr %#x.\n", hr);
1507  return hr;
1508  }
1509 
1510  if (!(clip_list = heap_alloc(clip_list_size)))
1511  {
1512  WARN("Failed to allocate clip list.\n");
1513  return E_OUTOFMEMORY;
1514  }
1515 
1516  if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
1517  &dst_rect, clip_list, &clip_list_size)))
1518  {
1519  WARN("Failed to get clip list, hr %#x.\n", hr);
1520  heap_free(clip_list);
1521  return hr;
1522  }
1523 
1524  clip_rect = (RECT *)clip_list->Buffer;
1525  for (i = 0; i < clip_list->rdh.nCount; ++i)
1526  {
1527  RECT src_rect_clipped = src_rect;
1528 
1529  if (src_surface)
1530  {
1531  src_rect_clipped.left += (LONG)((clip_rect[i].left - dst_rect.left) * scale_x);
1532  src_rect_clipped.top += (LONG)((clip_rect[i].top - dst_rect.top) * scale_y);
1533  src_rect_clipped.right -= (LONG)((dst_rect.right - clip_rect[i].right) * scale_x);
1534  src_rect_clipped.bottom -= (LONG)((dst_rect.bottom - clip_rect[i].bottom) * scale_y);
1535 
1537  {
1538  if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE)))
1539  break;
1540  }
1541  }
1542 
1543  if (FAILED(hr = ddraw_surface_blt(dst_surface, &clip_rect[i],
1544  src_surface, &src_rect_clipped, flags, fill_colour, fx, filter)))
1545  break;
1546 
1548  {
1549  if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE)))
1550  break;
1551  }
1552  }
1553 
1554  heap_free(clip_list);
1555  return hr;
1556 }
1557 
1558 /*****************************************************************************
1559  * IDirectDrawSurface7::Blt
1560  *
1561  * Performs a blit on the surface
1562  *
1563  * Params:
1564  * DestRect: Destination rectangle, can be NULL
1565  * SrcSurface: Source surface, can be NULL
1566  * SrcRect: Source rectangle, can be NULL
1567  * Flags: Blt flags
1568  * DDBltFx: Some extended blt parameters, connected to the flags
1569  *
1570  * Returns:
1571  * D3D_OK on success, error code otherwise.
1572  *
1573  *****************************************************************************/
1575  IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1576 {
1577  struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
1578  struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface);
1579  struct wined3d_blt_fx wined3d_fx;
1580  DWORD unsupported_flags;
1581  DWORD fill_colour = 0;
1582  HRESULT hr = DD_OK;
1583  DDBLTFX rop_fx;
1584 
1585  TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1586  iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1587 
1588  unsupported_flags = DDBLT_ALPHADEST
1593  | DDBLT_ALPHASRC
1597  | DDBLT_ZBUFFER
1602  if (flags & unsupported_flags)
1603  {
1604  WARN("Ignoring unsupported flags %#x.\n", flags & unsupported_flags);
1605  flags &= ~unsupported_flags;
1606  }
1607 
1608  if ((flags & DDBLT_KEYSRCOVERRIDE) && (!fx || flags & DDBLT_KEYSRC))
1609  {
1610  WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
1611  return DDERR_INVALIDPARAMS;
1612  }
1613 
1614  if ((flags & DDBLT_KEYDESTOVERRIDE) && (!fx || flags & DDBLT_KEYDEST))
1615  {
1616  WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
1617  return DDERR_INVALIDPARAMS;
1618  }
1619 
1620  if (flags & DDBLT_DDROPS)
1621  {
1622  FIXME("DDBLT_DDROPS not implemented.\n");
1623  if (fx)
1624  FIXME(" rop %#x, pattern %p.\n", fx->dwDDROP, fx->u5.lpDDSPattern);
1625  return DDERR_NORASTEROPHW;
1626  }
1627 
1629 
1631  {
1632  if (flags & DDBLT_ROP)
1633  {
1635  WARN("DDBLT_ROP used with DDBLT_COLORFILL or DDBLT_DEPTHFILL, returning DDERR_INVALIDPARAMS.\n");
1636  return DDERR_INVALIDPARAMS;
1637  }
1638  if (src_impl)
1639  {
1641  WARN("Depth or colorfill is not compatible with source surfaces, returning DDERR_INVALIDPARAMS\n");
1642  return DDERR_INVALIDPARAMS;
1643  }
1644  if (!fx)
1645  {
1647  WARN("Depth or colorfill used with NULL fx, returning DDERR_INVALIDPARAMS.\n");
1648  return DDERR_INVALIDPARAMS;
1649  }
1650 
1652  flags &= ~DDBLT_DEPTHFILL;
1653 
1655  {
1657  WARN("DDBLT_COLORFILL used on a depth buffer, returning DDERR_INVALIDPARAMS.\n");
1658  return DDERR_INVALIDPARAMS;
1659  }
1660  if (!(dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (flags & DDBLT_DEPTHFILL))
1661  {
1663  WARN("DDBLT_DEPTHFILL used on a color buffer, returning DDERR_INVALIDPARAMS.\n");
1664  return DDERR_INVALIDPARAMS;
1665  }
1666  }
1667 
1668  if (flags & DDBLT_ROP)
1669  {
1670  if (!fx)
1671  {
1673  WARN("DDBLT_ROP used with NULL fx, returning DDERR_INVALIDPARAMS.\n");
1674  return DDERR_INVALIDPARAMS;
1675  }
1676 
1677  if (src_impl && src_rect
1678  && ((ULONG)src_rect->left >= src_rect->right || src_rect->right > src_impl->surface_desc.dwWidth
1679  || (ULONG)src_rect->top >= src_rect->bottom || src_rect->bottom > src_impl->surface_desc.dwHeight))
1680  {
1681  WARN("Invalid source rectangle.\n");
1682  return DDERR_INVALIDRECT;
1683  }
1684 
1685  flags &= ~DDBLT_ROP;
1686  switch (fx->dwROP)
1687  {
1688  case SRCCOPY:
1689  break;
1690 
1691  case WHITENESS:
1692  case BLACKNESS:
1693  rop_fx = *fx;
1694 
1695  if (fx->dwROP == WHITENESS)
1696  rop_fx.u5.dwFillColor = 0xffffffff;
1697  else
1698  rop_fx.u5.dwFillColor = 0;
1699 
1700  if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1702  else
1704 
1705  fx = &rop_fx;
1706  break;
1707 
1708  default:
1710  WARN("Unsupported ROP %#x used, returning DDERR_NORASTEROPHW.\n", fx->dwROP);
1711  return DDERR_NORASTEROPHW;
1712  }
1713  }
1714 
1715  if (!(flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) && !src_impl)
1716  {
1717  WARN("No source surface.\n");
1718  return DDERR_INVALIDPARAMS;
1719  }
1720 
1721  if (flags & DDBLT_KEYSRC && (!src_impl || !(src_impl->surface_desc.dwFlags & DDSD_CKSRCBLT)))
1722  {
1723  WARN("DDBLT_KEYSRC blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1725  return DDERR_INVALIDPARAMS;
1726  }
1727  if (flags & DDBLT_KEYDEST && !(dst_impl->surface_desc.dwFlags & DDSD_CKDESTBLT))
1728  {
1729  WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1731  return DDERR_INVALIDPARAMS;
1732  }
1733 
1734  if (fx)
1735  {
1736  wined3d_fx.fx = fx->dwDDFX;
1737  fill_colour = fx->u5.dwFillColor;
1738  wined3d_fx.dst_color_key.color_space_low_value = fx->ddckDestColorkey.dwColorSpaceLowValue;
1739  wined3d_fx.dst_color_key.color_space_high_value = fx->ddckDestColorkey.dwColorSpaceHighValue;
1740  wined3d_fx.src_color_key.color_space_low_value = fx->ddckSrcColorkey.dwColorSpaceLowValue;
1741  wined3d_fx.src_color_key.color_space_high_value = fx->ddckSrcColorkey.dwColorSpaceHighValue;
1742  }
1743 
1744  hr = ddraw_surface_blt_clipped(dst_impl, dst_rect, src_impl,
1745  src_rect, flags, fill_colour, fx ? &wined3d_fx : NULL, WINED3D_TEXF_LINEAR);
1746 
1748  switch(hr)
1749  {
1751  default: return hr;
1752  }
1753 }
1754 
1755 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Blt(IDirectDrawSurface4 *iface, RECT *dst_rect,
1756  IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1757 {
1760 
1761  TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1762  iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1763 
1764  return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1765  src ? &src->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1766 }
1767 
1768 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Blt(IDirectDrawSurface3 *iface, RECT *dst_rect,
1769  IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1770 {
1772  struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
1773 
1774  TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1775  iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1776 
1777  return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1778  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1779 }
1780 
1781 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Blt(IDirectDrawSurface2 *iface, RECT *dst_rect,
1782  IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1783 {
1785  struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
1786 
1787  TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1788  iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1789 
1790  return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1791  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1792 }
1793 
1794 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Blt(IDirectDrawSurface *iface, RECT *dst_rect,
1795  IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1796 {
1798  struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
1799 
1800  TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1801  iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1802 
1803  return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1804  src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1805 }
1806 
1807 /*****************************************************************************
1808  * IDirectDrawSurface7::AddAttachedSurface
1809  *
1810  * Attaches a surface to another surface. How the surface attachments work
1811  * is not totally understood yet, and this method is prone to problems.
1812  * The surface that is attached is AddRef-ed.
1813  *
1814  * Tests with complex surfaces suggest that the surface attachments form a
1815  * tree, but no method to test this has been found yet.
1816  *
1817  * The attachment list consists of a first surface (first_attached) and
1818  * for each surface a pointer to the next attached surface (next_attached).
1819  * For the first surface, and a surface that has no attachments
1820  * first_attached points to the surface itself. A surface that has
1821  * no successors in the chain has next_attached set to NULL.
1822  *
1823  * Newly attached surfaces are attached right after the root surface.
1824  * If a surface is attached to a complex surface compound, it's attached to
1825  * the surface that the app requested, not the complex root. See
1826  * GetAttachedSurface for a description how surfaces are found.
1827  *
1828  * This is how the current implementation works, and it was coded by looking
1829  * at the needs of the applications.
1830  *
1831  * So far only Z-Buffer attachments are tested, and they are activated in
1832  * WineD3D. Mipmaps could be tricky to activate in WineD3D.
1833  * Back buffers should work in 2D mode, but they are not tested(They can be
1834  * attached in older iface versions). Rendering to the front buffer and
1835  * switching between that and double buffering is not yet implemented in
1836  * WineD3D, so for 3D it might have unexpected results.
1837  *
1838  * ddraw_surface_attach_surface is the real thing,
1839  * ddraw_surface7_AddAttachedSurface is a wrapper around it that
1840  * performs additional checks. Version 7 of this interface is much more restrictive
1841  * than its predecessors.
1842  *
1843  * Params:
1844  * Attach: Surface to attach to iface
1845  *
1846  * Returns:
1847  * DD_OK on success
1848  * DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
1849  *
1850  *****************************************************************************/
1852 {
1853  TRACE("surface %p, attachment %p.\n", This, Surf);
1854 
1855  if(Surf == This)
1856  return DDERR_CANNOTATTACHSURFACE; /* unchecked */
1857 
1859 
1860  /* Check if the surface is already attached somewhere */
1861  if (Surf->next_attached || Surf->first_attached != Surf)
1862  {
1863  /* TODO: Test for the structure of the manual attachment. Is it a
1864  * chain or a list? What happens if one surface is attached to 2
1865  * different surfaces? */
1866  WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n",
1867  Surf, Surf->next_attached, Surf->first_attached);
1868 
1871  }
1872 
1873  /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
1874  Surf->next_attached = This->next_attached;
1875  Surf->first_attached = This->first_attached;
1876  This->next_attached = Surf;
1877 
1878  /* Check if the WineD3D depth stencil needs updating */
1879  if (This->ddraw->d3ddevice)
1880  d3d_device_update_depth_stencil(This->ddraw->d3ddevice);
1881 
1883 
1884  return DD_OK;
1885 }
1886 
1888 {
1891  HRESULT hr;
1892 
1893  TRACE("iface %p, attachment %p.\n", iface, attachment);
1894 
1895  /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
1896  if(!(attachment_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
1897  {
1898 
1899  WARN("Application tries to attach a non Z buffer surface. caps %08x\n",
1900  attachment_impl->surface_desc.ddsCaps.dwCaps);
1902  }
1903 
1904  hr = ddraw_surface_attach_surface(This, attachment_impl);
1905  if (FAILED(hr))
1906  {
1907  return hr;
1908  }
1909  attachment_impl->attached_iface = (IUnknown *)attachment;
1910  IUnknown_AddRef(attachment_impl->attached_iface);
1911  return hr;
1912 }
1913 
1914 static HRESULT WINAPI ddraw_surface4_AddAttachedSurface(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *attachment)
1915 {
1916  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1918  HRESULT hr;
1919 
1920  TRACE("iface %p, attachment %p.\n", iface, attachment);
1921 
1922  /* Tests suggest that
1923  * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
1924  * -> offscreen plain surfaces can be attached to primaries
1925  * -> primaries can be attached to offscreen plain surfaces
1926  * -> z buffers can be attached to primaries */
1929  {
1930  /* Sizes have to match */
1931  if (attachment_impl->surface_desc.dwWidth != surface->surface_desc.dwWidth
1932  || attachment_impl->surface_desc.dwHeight != surface->surface_desc.dwHeight)
1933  {
1934  WARN("Surface sizes do not match.\n");
1936  }
1937  }
1939  || !(attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)))
1940  {
1941  WARN("Invalid attachment combination.\n");
1943  }
1944 
1945  if (FAILED(hr = ddraw_surface_attach_surface(surface, attachment_impl)))
1946  return hr;
1947 
1948  attachment_impl->attached_iface = (IUnknown *)attachment;
1949  IUnknown_AddRef(attachment_impl->attached_iface);
1950  return hr;
1951 }
1952 
1953 static HRESULT WINAPI ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *attachment)
1954 {
1955  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1957  HRESULT hr;
1958 
1959  TRACE("iface %p, attachment %p.\n", iface, attachment);
1960 
1962  attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
1963  return hr;
1964 
1965  attachment_impl->attached_iface = (IUnknown *)attachment;
1966  IUnknown_AddRef(attachment_impl->attached_iface);
1968  return hr;
1969 }
1970 
1971 static HRESULT WINAPI ddraw_surface2_AddAttachedSurface(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *attachment)
1972 {
1973  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1975  HRESULT hr;
1976 
1977  TRACE("iface %p, attachment %p.\n", iface, attachment);
1978 
1980  attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
1981  return hr;
1982 
1983  attachment_impl->attached_iface = (IUnknown *)attachment;
1984  IUnknown_AddRef(attachment_impl->attached_iface);
1986  return hr;
1987 }
1988 
1989 static HRESULT WINAPI ddraw_surface1_AddAttachedSurface(IDirectDrawSurface *iface, IDirectDrawSurface *attachment)
1990 {
1991  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1993  HRESULT hr;
1994 
1995  TRACE("iface %p, attachment %p.\n", iface, attachment);
1996 
1998  attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
1999  return hr;
2000 
2001  attachment_impl->attached_iface = (IUnknown *)attachment;
2002  IUnknown_AddRef(attachment_impl->attached_iface);
2004  return hr;
2005 }
2006 
2007 /*****************************************************************************
2008  * IDirectDrawSurface7::DeleteAttachedSurface
2009  *
2010  * Removes a surface from the attachment chain. The surface's refcount
2011  * is decreased by one after it has been removed
2012  *
2013  * Params:
2014  * Flags: Some flags, not used by this implementation
2015  * Attach: Surface to detach
2016  *
2017  * Returns:
2018  * DD_OK on success
2019  * DDERR_SURFACENOTATTACHED if the surface isn't attached to
2020  *
2021  *****************************************************************************/
2023  struct ddraw_surface *attachment, IUnknown *detach_iface)
2024 {
2025  struct ddraw_surface *prev = surface;
2026 
2027  TRACE("surface %p, attachment %p, detach_iface %p.\n", surface, attachment, detach_iface);
2028 
2030  if (!attachment || (attachment->first_attached != surface) || (attachment == surface) )
2031  {
2034  }
2035 
2036  if (attachment->attached_iface != detach_iface)
2037  {
2038  WARN("attachment->attach_iface %p != detach_iface %p.\n", attachment->attached_iface, detach_iface);
2040  return DDERR_SURFACENOTATTACHED;
2041  }
2042 
2043  /* Remove MIPMAPSUBLEVEL if this seemed to be one */
2044  if (surface->surface_desc.ddsCaps.dwCaps & attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
2045  {
2046  attachment->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
2047  /* FIXME: we should probably also subtract from dwMipMapCount of this
2048  * and all parent surfaces */
2049  }
2050 
2051  /* Find the predecessor of the detached surface */
2052  while (prev->next_attached != attachment)
2053  {
2054  if (!(prev = prev->next_attached))
2055  {
2056  ERR("Failed to find predecessor of %p.\n", attachment);
2058  return DDERR_SURFACENOTATTACHED;
2059  }
2060  }
2061 
2062  /* Unchain the surface */
2063  prev->next_attached = attachment->next_attached;
2064  attachment->next_attached = NULL;
2065  attachment->first_attached = attachment;
2066 
2067  /* Check if the wined3d depth stencil needs updating. Note that we don't
2068  * just call d3d_device_update_depth_stencil() here since it uses
2069  * QueryInterface(). Some applications, SCP - Containment Breach in
2070  * particular, modify the QueryInterface() pointer in the surface vtbl
2071  * but don't cleanup properly after the relevant dll is unloaded. */
2072  if (attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER
2073  && wined3d_device_get_depth_stencil_view(surface->ddraw->wined3d_device) == attachment->wined3d_rtv)
2074  wined3d_device_set_depth_stencil_view(surface->ddraw->wined3d_device, NULL);
2076 
2077  /* Set attached_iface to NULL before releasing it, the surface may go
2078  * away. */
2079  attachment->attached_iface = NULL;
2080  IUnknown_Release(detach_iface);
2081 
2082  return DD_OK;
2083 }
2084 
2087 {
2088  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2090 
2091  TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2092 
2093  return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2094 }
2095 
2096 static HRESULT WINAPI ddraw_surface4_DeleteAttachedSurface(IDirectDrawSurface4 *iface,
2097  DWORD flags, IDirectDrawSurface4 *attachment)
2098 {
2099  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2101 
2102  TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2103 
2104  return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2105 }
2106 
2107 static HRESULT WINAPI ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
2108  DWORD flags, IDirectDrawSurface3 *attachment)
2109 {
2110  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2112 
2113  TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2114 
2115  return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2116 }
2117 
2118 static HRESULT WINAPI ddraw_surface2_DeleteAttachedSurface(IDirectDrawSurface2 *iface,
2119  DWORD flags, IDirectDrawSurface2 *attachment)
2120 {
2121  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2123 
2124  TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2125 
2126  return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2127 }
2128 
2129 static HRESULT WINAPI ddraw_surface1_DeleteAttachedSurface(IDirectDrawSurface *iface,
2130  DWORD flags, IDirectDrawSurface *attachment)
2131 {
2132  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2134 
2135  TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2136 
2137  return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2138 }
2139 
2140 /*****************************************************************************
2141  * IDirectDrawSurface7::AddOverlayDirtyRect
2142  *
2143  * "This method is not currently implemented"
2144  *
2145  * Params:
2146  * Rect: ?
2147  *
2148  * Returns:
2149  * DDERR_UNSUPPORTED
2150  *
2151  *****************************************************************************/
2153 {
2154  TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(Rect));
2155 
2156  return DDERR_UNSUPPORTED; /* unchecked */
2157 }
2158 
2159 static HRESULT WINAPI ddraw_surface4_AddOverlayDirtyRect(IDirectDrawSurface4 *iface, RECT *rect)
2160 {
2161  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2162 
2163  TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2164 
2166 }
2167 
2168 static HRESULT WINAPI ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3 *iface, RECT *rect)
2169 {
2170  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2171 
2172  TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2173 
2175 }
2176 
2177 static HRESULT WINAPI ddraw_surface2_AddOverlayDirtyRect(IDirectDrawSurface2 *iface, RECT *rect)
2178 {
2179  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2180 
2181  TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2182 
2184 }
2185 
2186 static HRESULT WINAPI ddraw_surface1_AddOverlayDirtyRect(IDirectDrawSurface *iface, RECT *rect)
2187 {
2188  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2189 
2190  TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2191 
2193 }
2194 
2195 /*****************************************************************************
2196  * IDirectDrawSurface7::GetDC
2197  *
2198  * Returns a GDI device context for the surface
2199  *
2200  * Params:
2201  * hdc: Address of a HDC variable to store the dc to
2202  *
2203  * Returns:
2204  * DD_OK on success
2205  * DDERR_INVALIDPARAMS if hdc is NULL
2206  *
2207  *****************************************************************************/
2209 {
2210  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2211  HRESULT hr = DD_OK;
2212 
2213  TRACE("iface %p, dc %p.\n", iface, dc);
2214 
2215  if (!dc)
2216  return DDERR_INVALIDPARAMS;
2217 
2219  if (surface->dc)
2221  else if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2223  if (SUCCEEDED(hr))
2225 
2226  if (SUCCEEDED(hr))
2227  {
2228  surface->dc = *dc;
2229 
2231  {
2232  const struct ddraw_palette *palette;
2233 
2234  if (surface->palette)
2235  palette = surface->palette;
2236  else if (surface->ddraw->primary)
2237  palette = surface->ddraw->primary->palette;
2238  else
2239  palette = NULL;
2240 
2241  if (palette)
2242  wined3d_palette_apply_to_dc(palette->wined3d_palette, *dc);
2243  }
2244  }
2245 
2247  switch (hr)
2248  {
2249  /* Some, but not all errors set *dc to NULL. E.g. DCALREADYCREATED
2250  * does not touch *dc. */
2252  *dc = NULL;
2253  return DDERR_CANTCREATEDC;
2254 
2255  default:
2256  return hr;
2257  }
2258 }
2259 
2260 static HRESULT WINAPI ddraw_surface4_GetDC(IDirectDrawSurface4 *iface, HDC *dc)
2261 {
2262  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2263 
2264  TRACE("iface %p, dc %p.\n", iface, dc);
2265 
2267 }
2268 
2269 static HRESULT WINAPI ddraw_surface3_GetDC(IDirectDrawSurface3 *iface, HDC *dc)
2270 {
2271  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2272 
2273  TRACE("iface %p, dc %p.\n", iface, dc);
2274 
2276 }
2277 
2278 static HRESULT WINAPI ddraw_surface2_GetDC(IDirectDrawSurface2 *iface, HDC *dc)
2279 {
2280  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2281 
2282  TRACE("iface %p, dc %p.\n", iface, dc);
2283 
2285 }
2286 
2287 static HRESULT WINAPI ddraw_surface1_GetDC(IDirectDrawSurface *iface, HDC *dc)
2288 {
2289  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2290 
2291  TRACE("iface %p, dc %p.\n", iface, dc);
2292 
2294 }
2295 
2296 /*****************************************************************************
2297  * IDirectDrawSurface7::ReleaseDC
2298  *
2299  * Releases the DC that was constructed with GetDC
2300  *
2301  * Params:
2302  * hdc: HDC to release
2303  *
2304  * Returns:
2305  * DD_OK on success, error code otherwise.
2306  *
2307  *****************************************************************************/
2309 {
2310  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2311  HRESULT hr;
2312 
2313  TRACE("iface %p, dc %p.\n", iface, hdc);
2314 #ifdef __REACTOS__
2315  GdiFlush();
2316 #endif
2318  if (!surface->dc)
2319  {
2320  hr = DDERR_NODC;
2321  }
2323  {
2324  surface->dc = NULL;
2327  }
2329 
2330 
2331  return hr;
2332 }
2333 
2334 static HRESULT WINAPI ddraw_surface4_ReleaseDC(IDirectDrawSurface4 *iface, HDC dc)
2335 {
2336  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2337 
2338  TRACE("iface %p, dc %p.\n", iface, dc);
2339 
2341 }
2342 
2343 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc)
2344 {
2345  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2346 
2347  TRACE("iface %p, dc %p.\n", iface, dc);
2348 
2350 }
2351 
2352 static HRESULT WINAPI ddraw_surface2_ReleaseDC(IDirectDrawSurface2 *iface, HDC dc)
2353 {
2354  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2355 
2356  TRACE("iface %p, dc %p.\n", iface, dc);
2357 
2359 }
2360 
2361 static HRESULT WINAPI ddraw_surface1_ReleaseDC(IDirectDrawSurface *iface, HDC dc)
2362 {
2363  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2364 
2365  TRACE("iface %p, dc %p.\n", iface, dc);
2366 
2368 }
2369 
2370 /*****************************************************************************
2371  * IDirectDrawSurface7::GetCaps
2372  *
2373  * Returns the surface's caps
2374  *
2375  * Params:
2376  * Caps: Address to write the caps to
2377  *
2378  * Returns:
2379  * DD_OK on success
2380  * DDERR_INVALIDPARAMS if Caps is NULL
2381  *
2382  *****************************************************************************/
2384 {
2385  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2386 
2387  TRACE("iface %p, caps %p.\n", iface, Caps);
2388 
2389  if(!Caps)
2390  return DDERR_INVALIDPARAMS;
2391 
2392  *Caps = surface->surface_desc.ddsCaps;
2393 
2394  return DD_OK;
2395 }
2396 
2397 static HRESULT WINAPI ddraw_surface4_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *caps)
2398 {
2399  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2400 
2401  TRACE("iface %p, caps %p.\n", iface, caps);
2402 
2403  return ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, caps);
2404 }
2405 
2406 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps)
2407 {
2408  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2409  DDSCAPS2 caps2;
2410  HRESULT hr;
2411 
2412  TRACE("iface %p, caps %p.\n", iface, caps);
2413 
2415  if (FAILED(hr)) return hr;
2416 
2417  caps->dwCaps = caps2.dwCaps;
2418  return hr;
2419 }
2420 
2421 static HRESULT WINAPI ddraw_surface2_GetCaps(IDirectDrawSurface2 *iface, DDSCAPS *caps)
2422 {
2423  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2424  DDSCAPS2 caps2;
2425  HRESULT hr;
2426 
2427  TRACE("iface %p, caps %p.\n", iface, caps);
2428 
2430  if (FAILED(hr)) return hr;
2431 
2432  caps->dwCaps = caps2.dwCaps;
2433  return hr;
2434 }
2435 
2436 static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS *caps)
2437 {
2438  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2439  DDSCAPS2 caps2;
2440  HRESULT hr;
2441 
2442  TRACE("iface %p, caps %p.\n", iface, caps);
2443 
2445  if (FAILED(hr)) return hr;
2446 
2447  caps->dwCaps = caps2.dwCaps;
2448  return hr;
2449 }
2450 
2452 {
2453  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2455  HRESULT hr;
2456  struct wined3d_resource *resource;
2457 
2458  TRACE("iface %p, priority %u.\n", iface, priority);
2459 
2461  /* No need to check for offscreen plain surfaces or mipmap sublevels. SetPriority
2462  * calls on such surfaces segfault on Windows. */
2463  if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed))
2464  {
2465  WARN("Called on non-managed texture returning DDERR_INVALIDPARAMS.\n");
2467  }
2468  else
2469  {
2472  hr = DD_OK;
2473  }
2475 
2476  return hr;
2477 }
2478 
2480 {
2481  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2482  const struct wined3d_resource *resource;
2484  HRESULT hr;
2485 
2486  TRACE("iface %p, priority %p.\n", iface, priority);
2487 
2490  {
2491  WARN("Called on offscreenplain surface, returning DDERR_INVALIDOBJECT.\n");
2493  }
2494  else if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed) || !surface->is_complex_root)
2495  {
2496  WARN("Called on non-managed texture or non-root surface, returning DDERR_INVALIDPARAMS.\n");
2498  }
2499  else
2500  {
2503  hr = DD_OK;
2504  }
2506 
2507  return hr;
2508 }
2509 
2510 /*****************************************************************************
2511  * IDirectDrawSurface7::SetPrivateData
2512  *
2513  * Stores some data in the surface that is intended for the application's
2514  * use.
2515  *
2516  * Params:
2517  * tag: GUID that identifies the data
2518  * Data: Pointer to the private data
2519  * Size: Size of the private data
2520  * Flags: Some flags
2521  *
2522  * Returns:
2523  * D3D_OK on success, error code otherwise.
2524  *
2525  *****************************************************************************/
2527  REFGUID tag, void *data, DWORD size, DWORD flags)
2528 {
2529  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2530  HRESULT hr;
2531 
2532  TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2533  iface, debugstr_guid(tag), data, size, flags);
2534 
2535  if (!data)
2536  {
2537  WARN("data is NULL, returning DDERR_INVALIDPARAMS.\n");
2538  return DDERR_INVALIDPARAMS;
2539  }
2540 
2544  return hr_ddraw_from_wined3d(hr);
2545 }
2546 
2547 static HRESULT WINAPI ddraw_surface4_SetPrivateData(IDirectDrawSurface4 *iface,
2548  REFGUID tag, void *data, DWORD size, DWORD flags)
2549 {
2550  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2551 
2552  TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2553  iface, debugstr_guid(tag), data, size, flags);
2554 
2556 }
2557 
2558 /*****************************************************************************
2559  * IDirectDrawSurface7::GetPrivateData
2560  *
2561  * Returns the private data set with IDirectDrawSurface7::SetPrivateData
2562  *
2563  * Params:
2564  * tag: GUID of the data to return
2565  * Data: Address where to write the data to
2566  * Size: Size of the buffer at Data
2567  *
2568  * Returns:
2569  * DD_OK on success
2570  * DDERR_INVALIDPARAMS if Data is NULL
2571  *
2572  *****************************************************************************/
2574 {
2575  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2576  const struct wined3d_private_data *stored_data;
2577  HRESULT hr;
2578 
2579  TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2580  iface, debugstr_guid(tag), data, size);
2581 
2583  stored_data = wined3d_private_store_get_private_data(&surface->private_store, tag);
2584  if (!stored_data)
2585  {
2586  hr = DDERR_NOTFOUND;
2587  goto done;
2588  }
2589  if (!size)
2590  {
2592  goto done;
2593  }
2595  {
2596  *size = stored_data->size;
2597  hr = DDERR_MOREDATA;
2598  goto done;
2599  }
2600  if (!data)
2601  {
2603  goto done;
2604  }
2605 
2606  *size = stored_data->size;
2607  memcpy(data, stored_data->content.data, stored_data->size);
2608  hr = DD_OK;
2609 
2610 done:
2612  return hr;
2613 }
2614 
2615 static HRESULT WINAPI ddraw_surface4_GetPrivateData(IDirectDrawSurface4 *iface, REFGUID tag, void *data, DWORD *size)
2616 {
2617  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2618 
2619  TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2620  iface, debugstr_guid(tag), data, size);
2621 
2623 }
2624 
2625 /*****************************************************************************
2626  * IDirectDrawSurface7::FreePrivateData
2627  *
2628  * Frees private data stored in the surface
2629  *
2630  * Params:
2631  * tag: Tag of the data to free
2632  *
2633  * Returns:
2634  * D3D_OK on success, error code otherwise.
2635  *
2636  *****************************************************************************/
2638 {
2639  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2640  struct wined3d_private_data *entry;
2641 
2642  TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2643 
2646  if (!entry)
2647  {
2649  return DDERR_NOTFOUND;
2650  }
2651 
2654 
2655  return DD_OK;
2656 }
2657 
2658 static HRESULT WINAPI ddraw_surface4_FreePrivateData(IDirectDrawSurface4 *iface, REFGUID tag)
2659 {
2660  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2661 
2662  TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2663 
2665 }
2666 
2667 /*****************************************************************************
2668  * IDirectDrawSurface7::PageLock
2669  *
2670  * Prevents a sysmem surface from being paged out
2671  *
2672  * Params:
2673  * Flags: Not used, must be 0(unchecked)
2674  *
2675  * Returns:
2676  * DD_OK, because it's a stub
2677  *
2678  *****************************************************************************/
2680 {
2681  TRACE("iface %p, flags %#x.\n", iface, Flags);
2682 
2683  /* This is Windows memory management related - we don't need this */
2684  return DD_OK;
2685 }
2686 
2687 static HRESULT WINAPI ddraw_surface4_PageLock(IDirectDrawSurface4 *iface, DWORD flags)
2688 {
2689  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2690 
2691  TRACE("iface %p, flags %#x.\n", iface, flags);
2692 
2694 }
2695 
2696 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags)
2697 {
2698  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2699 
2700  TRACE("iface %p, flags %#x.\n", iface, flags);
2701 
2703 }
2704 
2705 static HRESULT WINAPI ddraw_surface2_PageLock(IDirectDrawSurface2 *iface, DWORD flags)
2706 {
2707  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2708 
2709  TRACE("iface %p, flags %#x.\n", iface, flags);
2710 
2712 }
2713 
2714 /*****************************************************************************
2715  * IDirectDrawSurface7::PageUnlock
2716  *
2717  * Allows a sysmem surface to be paged out
2718  *
2719  * Params:
2720  * Flags: Not used, must be 0(unchecked)
2721  *
2722  * Returns:
2723  * DD_OK, because it's a stub
2724  *
2725  *****************************************************************************/
2727 {
2728  TRACE("iface %p, flags %#x.\n", iface, Flags);
2729 
2730  return DD_OK;
2731 }
2732 
2733 static HRESULT WINAPI ddraw_surface4_PageUnlock(IDirectDrawSurface4 *iface, DWORD flags)
2734 {
2735  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2736 
2737  TRACE("iface %p, flags %#x.\n", iface, flags);
2738 
2740 }
2741 
2742 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags)
2743 {
2744  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2745 
2746  TRACE("iface %p, flags %#x.\n", iface, flags);
2747 
2749 }
2750 
2751 static HRESULT WINAPI ddraw_surface2_PageUnlock(IDirectDrawSurface2 *iface, DWORD flags)
2752 {
2753  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2754 
2755  TRACE("iface %p, flags %#x.\n", iface, flags);
2756 
2758 }
2759 
2760 /*****************************************************************************
2761  * IDirectDrawSurface7::BltBatch
2762  *
2763  * An unimplemented function
2764  *
2765  * Params:
2766  * ?
2767  *
2768  * Returns:
2769  * DDERR_UNSUPPORTED
2770  *
2771  *****************************************************************************/
2773 {
2774  TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, Batch, Count, Flags);
2775 
2776  /* MSDN: "not currently implemented" */
2777  return DDERR_UNSUPPORTED;
2778 }
2779 
2781 {
2782  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2783 
2784  TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2785 
2786  return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2787 }
2788 
2790 {
2791  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2792 
2793  TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2794 
2795  return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2796 }
2797 
2799 {
2800  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2801 
2802  TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2803 
2804  return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2805 }
2806 
2808 {
2809  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2810 
2811  TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2812 
2813  return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2814 }
2815 
2816 /*****************************************************************************
2817  * IDirectDrawSurface7::EnumAttachedSurfaces
2818  *
2819  * Enumerates all surfaces attached to this surface
2820  *
2821  * Params:
2822  * context: Pointer to pass unmodified to the callback
2823  * cb: Callback function to call for each surface
2824  *
2825  * Returns:
2826  * DD_OK on success
2827  * DDERR_INVALIDPARAMS if cb is NULL
2828  *
2829  *****************************************************************************/
2832 {
2833  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2834  struct ddraw_surface *surf;
2836  int i;
2837 
2838  /* Attached surfaces aren't handled in WineD3D */
2839  TRACE("iface %p, context %p, callback %p.\n", iface, context, cb);
2840 
2841  if(!cb)
2842  return DDERR_INVALIDPARAMS;
2843 
2845 
2846  for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
2847  {
2848  surf = surface->complex_array[i];
2849  if(!surf) break;
2850 
2852  desc = surf->surface_desc;
2853  /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2855  {
2857  return DD_OK;
2858  }
2859  }
2860 
2861  for (surf = surface->next_attached; surf != NULL; surf = surf->next_attached)
2862  {
2864  desc = surf->surface_desc;
2865  /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2867  {
2869  return DD_OK;
2870  }
2871  }
2872 
2873  TRACE(" end of enumeration.\n");
2874 
2876 
2877  return DD_OK;
2878 }
2879 
2881 {
2883  void *context;
2884 };
2885 
2886 struct callback_info
2887 {
2889  void *context;
2890 };
2891 
2893 {
2894  struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
2895  const struct callback_info2 *info = context;
2896 
2898  ddraw_surface7_Release(surface);
2899 
2900  return info->callback(&surface_impl->IDirectDrawSurface4_iface, surface_desc, info->context);
2901 }
2902 
2904 {
2905  struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
2906  const struct callback_info *info = context;
2907 
2909  ddraw_surface7_Release(surface);
2910 
2911  /* FIXME: Check surface_test.dwSize */
2912  return info->callback(&surface_impl->IDirectDrawSurface_iface,
2913  (DDSURFACEDESC *)surface_desc, info->context);
2914 }
2915 
2916 static HRESULT WINAPI ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4 *iface,
2918 {
2919  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2920  struct callback_info2 info;
2921 
2922  TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2923 
2924  info.callback = callback;
2925  info.context = context;
2926 
2928  &info, EnumCallback2);
2929 }
2930 
2931 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
2933 {
2934  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2935  struct callback_info info;
2936 
2937  TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2938 
2939  info.callback = callback;
2940  info.context = context;
2941 
2943  &info, EnumCallback);
2944 }
2945 
2946 static HRESULT WINAPI ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2 *iface,
2948 {
2949  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2950  struct callback_info info;
2951 
2952  TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2953 
2954  info.callback = callback;
2955  info.context = context;
2956 
2958  &info, EnumCallback);
2959 }
2960 
2961 static HRESULT WINAPI ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface *iface,
2963 {
2964  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2965  struct callback_info info;
2966 
2967  TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2968 
2969  info.callback = callback;
2970  info.context = context;
2971 
2973  &info, EnumCallback);
2974 }
2975 
2976 /*****************************************************************************
2977  * IDirectDrawSurface7::EnumOverlayZOrders
2978  *
2979  * "Enumerates the overlay surfaces on the specified destination"
2980  *
2981  * Params:
2982  * Flags: DDENUMOVERLAYZ_BACKTOFRONT or DDENUMOVERLAYZ_FRONTTOBACK
2983  * context: context to pass back to the callback
2984  * cb: callback function to call for each enumerated surface
2985  *
2986  * Returns:
2987  * DD_OK, because it's a stub
2988  *
2989  *****************************************************************************/
2992 {
2993  FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface, Flags, context, cb);
2994 
2995  return DD_OK;
2996 }
2997 
2998 static HRESULT WINAPI ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4 *iface,
3000 {
3001  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3002  struct callback_info2 info;
3003 
3004  TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3005 
3006  info.callback = callback;
3007  info.context = context;
3008 
3010  flags, &info, EnumCallback2);
3011 }
3012 
3013 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
3015 {
3016  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3017  struct callback_info info;
3018 
3019  TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3020 
3021  info.callback = callback;
3022  info.context = context;
3023 
3025  flags, &info, EnumCallback);
3026 }
3027 
3028 static HRESULT WINAPI ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2 *iface,
3030 {
3031  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3032  struct callback_info info;
3033 
3034  TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3035 
3036  info.callback = callback;
3037  info.context = context;
3038 
3040  flags, &info, EnumCallback);
3041 }
3042 
3043 static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *iface,
3045 {
3046  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3047  struct callback_info info;
3048 
3049  TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
3050 
3051  info.callback = callback;
3052  info.context = context;
3053 
3055  flags, &info, EnumCallback);
3056 }
3057 
3058 /*****************************************************************************
3059  * IDirectDrawSurface7::GetBltStatus
3060  *
3061  * Returns the blitting status
3062  *
3063  * Params:
3064  * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
3065  *
3066  *****************************************************************************/
3068 {
3069  TRACE("iface %p, flags %#x.\n", iface, Flags);
3070 
3071  switch (Flags)
3072  {
3073  case WINEDDGBS_CANBLT:
3074  case WINEDDGBS_ISBLTDONE:
3075  return DD_OK;
3076 
3077  default:
3078  return DDERR_INVALIDPARAMS;
3079  }
3080 }
3081 
3082 static HRESULT WINAPI ddraw_surface4_GetBltStatus(IDirectDrawSurface4 *iface, DWORD flags)
3083 {
3084  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3085 
3086  TRACE("iface %p, flags %#x.\n", iface, flags);
3087 
3089 }
3090 
3091 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags)
3092 {
3093  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3094 
3095  TRACE("iface %p, flags %#x.\n", iface, flags);
3096 
3098 }
3099 
3100 static HRESULT WINAPI ddraw_surface2_GetBltStatus(IDirectDrawSurface2 *iface, DWORD flags)
3101 {
3102  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3103 
3104  TRACE("iface %p, flags %#x.\n", iface, flags);
3105 
3107 }
3108 
3109 static HRESULT WINAPI ddraw_surface1_GetBltStatus(IDirectDrawSurface *iface, DWORD flags)
3110 {
3111  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3112 
3113  TRACE("iface %p, flags %#x.\n", iface, flags);
3114 
3116 }
3117 
3118 /*****************************************************************************
3119  * IDirectDrawSurface7::GetColorKey
3120  *
3121  * Returns the color key assigned to the surface
3122  *
3123  * Params:
3124  * Flags: Some flags
3125  * CKey: Address to store the key to
3126  *
3127  * Returns:
3128  * DD_OK on success
3129  * DDERR_INVALIDPARAMS if CKey is NULL
3130  *
3131  *****************************************************************************/
3133 {
3135 
3136  TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
3137 
3138  if(!CKey)
3139  return DDERR_INVALIDPARAMS;
3140 
3142 
3143  switch (Flags)
3144  {
3145  case DDCKEY_DESTBLT:
3146  if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT))
3147  {
3149  return DDERR_NOCOLORKEY;
3150  }
3151  *CKey = This->surface_desc.ddckCKDestBlt;
3152  break;
3153 
3154  case DDCKEY_DESTOVERLAY:
3155  if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY))
3156  {
3158  return DDERR_NOCOLORKEY;
3159  }
3160  *CKey = This->surface_desc.u3.ddckCKDestOverlay;
3161  break;
3162 
3163  case DDCKEY_SRCBLT:
3164  if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT))
3165  {
3167  return DDERR_NOCOLORKEY;
3168  }
3169  *CKey = This->surface_desc.ddckCKSrcBlt;
3170  break;
3171 
3172  case DDCKEY_SRCOVERLAY:
3173  if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY))
3174  {
3176  return DDERR_NOCOLORKEY;
3177  }
3178  *CKey = This->surface_desc.ddckCKSrcOverlay;
3179  break;
3180 
3181  default:
3183  return DDERR_INVALIDPARAMS;
3184  }
3185 
3187 
3188  return DD_OK;
3189 }
3190 
3192 {
3193  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3194 
3195  TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3196 
3198 }
3199 
3201 {
3202  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3203 
3204  TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3205 
3207 }
3208 
3210 {
3211  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3212 
3213  TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3214 
3216 }
3217 
3219 {
3220  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3221 
3222  TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3223 
3225 }
3226 
3227 /*****************************************************************************
3228  * IDirectDrawSurface7::GetFlipStatus
3229  *
3230  * Returns the flipping status of the surface
3231  *
3232  * Params:
3233  * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
3234  *
3235  *****************************************************************************/
3237 {
3238  TRACE("iface %p, flags %#x.\n", iface, Flags);
3239 
3240  /* XXX: DDERR_INVALIDSURFACETYPE */
3241 
3242  switch (Flags)
3243  {
3244  case WINEDDGFS_CANFLIP:
3245  case WINEDDGFS_ISFLIPDONE:
3246  return DD_OK;
3247 
3248  default:
3249  return DDERR_INVALIDPARAMS;
3250  }
3251 }
3252 
3253 static HRESULT WINAPI ddraw_surface4_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD flags)
3254 {
3255  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3256 
3257  TRACE("iface %p, flags %#x.\n", iface, flags);
3258 
3260 }
3261 
3262 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags)
3263 {
3264  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3265 
3266  TRACE("iface %p, flags %#x.\n", iface, flags);
3267 
3269 }
3270 
3271 static HRESULT WINAPI ddraw_surface2_GetFlipStatus(IDirectDrawSurface2 *iface, DWORD flags)
3272 {
3273  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3274 
3275  TRACE("iface %p, flags %#x.\n", iface, flags);
3276 
3278 }
3279 
3280 static HRESULT WINAPI ddraw_surface1_GetFlipStatus(IDirectDrawSurface *iface, DWORD flags)
3281 {
3282  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3283 
3284  TRACE("iface %p, flags %#x.\n", iface, flags);
3285 
3287 }
3288 
3289 /*****************************************************************************
3290  * IDirectDrawSurface7::GetOverlayPosition
3291  *
3292  * Returns the display coordinates of a visible and active overlay surface
3293  *
3294  * Params:
3295  * X
3296  * Y
3297  *
3298  * Returns:
3299  * DDERR_NOTAOVERLAYSURFACE, because it's a stub
3300  *****************************************************************************/
3302 {
3303  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3304  HRESULT hr;
3305 
3306  TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3307 
3310  surface->sub_resource_idx, x, y);
3312 
3313  return hr;
3314 }
3315 
3316 static HRESULT WINAPI ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4 *iface, LONG *x, LONG *y)
3317 {
3318  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3319 
3320  TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3321 
3323 }
3324 
3325 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y)
3326 {
3327  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3328 
3329  TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3330 
3332 }
3333 
3334 static HRESULT WINAPI ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2 *iface, LONG *x, LONG *y)
3335 {
3336  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3337 
3338  TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3339 
3341 }
3342 
3343 static HRESULT WINAPI ddraw_surface1_GetOverlayPosition(IDirectDrawSurface *iface, LONG *x, LONG *y)
3344 {
3345  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3346 
3347  TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3348 
3350 }
3351 
3352 /*****************************************************************************
3353  * IDirectDrawSurface7::GetPixelFormat
3354  *
3355  * Returns the pixel format of the Surface
3356  *
3357  * Params:
3358  * PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
3359  * format should be written
3360  *
3361  * Returns:
3362  * DD_OK on success
3363  * DDERR_INVALIDPARAMS if PixelFormat is NULL
3364  *
3365  *****************************************************************************/
3367 {
3368  /* What is DDERR_INVALIDSURFACETYPE for here? */
3369  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3370 
3371  TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat);
3372 
3373  if(!PixelFormat)
3374  return DDERR_INVALIDPARAMS;
3375 
3379 
3380  return DD_OK;
3381 }
3382 
3384 {
3385  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3386 
3387  TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3388 
3390 }
3391 
3393 {
3394  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3395 
3396  TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3397 
3399 }
3400 
3402 {
3403  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3404 
3405  TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3406 
3408 }
3409 
3411 {
3412  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3413 
3414  TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3415 
3417 }
3418 
3419 /*****************************************************************************
3420  * IDirectDrawSurface7::GetSurfaceDesc
3421  *
3422  * Returns the description of this surface
3423  *
3424  * Params:
3425  * DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
3426  * surface desc
3427  *
3428  * Returns:
3429  * DD_OK on success
3430  * DDERR_INVALIDPARAMS if DDSD is NULL
3431  *
3432  *****************************************************************************/
3434 {
3435  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3436 
3437  TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3438 
3439  if(!DDSD)
3440  return DDERR_INVALIDPARAMS;
3441 
3442  if (DDSD->dwSize != sizeof(DDSURFACEDESC2))
3443  {
3444  WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize);
3445  return DDERR_INVALIDPARAMS;
3446  }
3447 
3449  DD_STRUCT_COPY_BYSIZE(DDSD, &surface->surface_desc);
3450  TRACE("Returning surface desc:\n");
3453 
3454  return DD_OK;
3455 }
3456 
3457 static HRESULT WINAPI ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4 *iface, DDSURFACEDESC2 *DDSD)
3458 {
3459  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3460 
3461  TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3462 
3464 }
3465 
3467 {
3468  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3469 
3470  TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
3471 
3472  if (!surface_desc) return DDERR_INVALIDPARAMS;
3473 
3474  if (surface_desc->dwSize != sizeof(DDSURFACEDESC))
3475  {
3476  WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize);
3477  return DDERR_INVALIDPARAMS;
3478  }
3479 
3482  TRACE("Returning surface desc:\n");
3483  if (TRACE_ON(ddraw))
3484  {
3485  /* DDRAW_dump_surface_desc handles the smaller size */
3487  }
3489 
3490  return DD_OK;
3491 }
3492 
3493 static HRESULT WINAPI ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2 *iface, DDSURFACEDESC *DDSD)
3494 {
3495  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3496 
3497  TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3498 
3500 }
3501 
3502 static HRESULT WINAPI ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface *iface, DDSURFACEDESC *DDSD)
3503 {
3504  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3505 
3506  TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3507 
3509 }
3510 
3511 /*****************************************************************************
3512  * IDirectDrawSurface7::Initialize
3513  *
3514  * Initializes the surface. This is a no-op in Wine
3515  *
3516  * Params:
3517  * DD: Pointer to an DirectDraw interface
3518  * DDSD: Surface description for initialization
3519  *
3520  * Returns:
3521  * DDERR_ALREADYINITIALIZED
3522  *
3523  *****************************************************************************/
3525  IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3526 {
3527  TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3528 
3529  return DDERR_ALREADYINITIALIZED;
3530 }
3531 
3532 static HRESULT WINAPI ddraw_surface4_Initialize(IDirectDrawSurface4 *iface,
3533  IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3534 {
3535  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3536 
3537  TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3538 
3540  ddraw, surface_desc);
3541 }
3542 
3543 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface,
3544  IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3545 {
3546  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3547  DDSURFACEDESC2 surface_desc2;
3548 
3549  TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3550 
3551  if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3553  ddraw, surface_desc ? &surface_desc2 : NULL);
3554 }
3555 
3556 static HRESULT WINAPI ddraw_surface2_Initialize(IDirectDrawSurface2 *iface,
3557  IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3558 {
3559  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3560  DDSURFACEDESC2 surface_desc2;
3561 
3562  TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3563 
3564  if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3566  ddraw, surface_desc ? &surface_desc2 : NULL);
3567 }
3568 
3569 static HRESULT WINAPI ddraw_surface1_Initialize(IDirectDrawSurface *iface,
3570  IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3571 {
3572  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3573  DDSURFACEDESC2 surface_desc2;
3574 
3575  TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3576 
3577  if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3579  ddraw, surface_desc ? &surface_desc2 : NULL);
3580 }
3581 
3582 /*****************************************************************************
3583  * IDirect3DTexture1::Initialize
3584  *
3585  * The sdk says it's not implemented
3586  *
3587  * Params:
3588  * ?
3589  *
3590  * Returns
3591  * DDERR_UNSUPPORTED
3592  *
3593  *****************************************************************************/
3594 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface,
3595  IDirect3DDevice *device, IDirectDrawSurface *surface)
3596 {
3597  TRACE("iface %p, device %p, surface %p.\n", iface, device, surface);
3598 
3599  return DDERR_UNSUPPORTED; /* Unchecked */
3600 }
3601 
3602 /*****************************************************************************
3603  * IDirectDrawSurface7::IsLost
3604  *
3605  * Checks if the surface is lost
3606  *
3607  * Returns:
3608  * DD_OK, if the surface is usable
3609  * DDERR_ISLOST if the surface is lost
3610  *
3611  *****************************************************************************/
3613 {
3614  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3615 
3616  TRACE("iface %p.\n", iface);
3617 
3618  if (surface->ddraw->device_state != DDRAW_DEVICE_STATE_OK || surface->is_lost)
3619  return DDERR_SURFACELOST;
3620 
3621  return DD_OK;
3622 }
3623 
3624 static HRESULT WINAPI ddraw_surface4_IsLost(IDirectDrawSurface4 *iface)
3625 {
3626  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3627 
3628  TRACE("iface %p.\n", iface);
3629 
3631 }
3632 
3633 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface)
3634 {
3635  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3636 
3637  TRACE("iface %p.\n", iface);
3638 
3640 }
3641 
3642 static HRESULT WINAPI ddraw_surface2_IsLost(IDirectDrawSurface2 *iface)
3643 {
3644  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3645 
3646  TRACE("iface %p.\n", iface);
3647 
3649 }
3650 
3651 static HRESULT WINAPI ddraw_surface1_IsLost(IDirectDrawSurface *iface)
3652 {
3653  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3654 
3655  TRACE("iface %p.\n", iface);
3656 
3658 }
3659 
3660 /*****************************************************************************
3661  * IDirectDrawSurface7::Restore
3662  *
3663  * Restores a lost surface. This makes the surface usable again, but
3664  * doesn't reload its old contents
3665  *
3666  * Returns:
3667  * DD_OK on success, error code otherwise.
3668  *
3669  *****************************************************************************/
3671 {
3672  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3673 
3674  TRACE("iface %p.\n", iface);
3675 
3677  {
3678  struct wined3d_swapchain *swapchain = surface->ddraw->wined3d_swapchain;
3679  struct wined3d_sub_resource_desc wined3d_desc;
3680  struct wined3d_display_mode mode;
3681  HRESULT hr;
3682 
3683  if (FAILED(hr = wined3d_swapchain_get_display_mode(swapchain, &mode, NULL)))
3684  {
3685  WARN("Failed to get display mode, hr %#x.\n", hr);
3686  return hr;
3687  }
3688 
3689  if (FAILED(hr = wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, 0, &wined3d_desc)))
3690  {
3691  WARN("Failed to get resource desc, hr %#x.\n", hr);
3692  return hr;
3693  }
3694 
3695  if (mode.width != wined3d_desc.width || mode.height != wined3d_desc.height)
3696  {
3697  WARN("Display mode dimensions %ux%u don't match surface dimensions %ux%u.\n",
3698  mode.width, mode.height, wined3d_desc.width, wined3d_desc.height);
3699  return DDERR_WRONGMODE;
3700  }
3701 
3702  if (mode.format_id != wined3d_desc.format)
3703  {
3704  WARN("Display mode format %#x doesn't match surface format %#x.\n",
3705  mode.format_id, wined3d_desc.format);
3706  return DDERR_WRONGMODE;
3707  }
3708  }
3709 
3711  surface->is_lost = FALSE;
3712 
3713  return DD_OK;
3714 }
3715 
3716 static HRESULT WINAPI ddraw_surface4_Restore(IDirectDrawSurface4 *iface)
3717 {
3718  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3719 
3720  TRACE("iface %p.\n", iface);
3721 
3723 }
3724 
3725 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface)
3726 {
3727  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3728 
3729  TRACE("iface %p.\n", iface);
3730 
3732 }
3733 
3734 static HRESULT WINAPI ddraw_surface2_Restore(IDirectDrawSurface2 *iface)
3735 {
3736  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3737 
3738  TRACE("iface %p.\n", iface);
3739 
3741 }
3742 
3743 static HRESULT WINAPI ddraw_surface1_Restore(IDirectDrawSurface *iface)
3744 {
3745  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3746 
3747  TRACE("iface %p.\n", iface);
3748 
3750 }
3751 
3752 /*****************************************************************************
3753  * IDirectDrawSurface7::SetOverlayPosition
3754  *
3755  * Changes the display coordinates of an overlay surface
3756  *
3757  * Params:
3758  * X:
3759  * Y:
3760  *
3761  * Returns:
3762  * DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
3763  *****************************************************************************/
3765 {
3766  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3767  HRESULT hr;
3768 
3769  TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3770 
3773  surface->sub_resource_idx, x, y);
3775 
3776  return hr;
3777 }
3778 
3779 static HRESULT WINAPI ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4 *iface, LONG x, LONG y)
3780 {
3781  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3782 
3783  TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3784 
3786 }
3787 
3788 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y)
3789 {
3790  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3791 
3792  TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3793 
3795 }
3796 
3797 static HRESULT WINAPI ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2 *iface, LONG x, LONG y)
3798 {
3799  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3800 
3801  TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3802 
3804 }
3805 
3806 static HRESULT WINAPI ddraw_surface1_SetOverlayPosition(IDirectDrawSurface *iface, LONG x, LONG y)
3807 {
3808  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3809 
3810  TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3811 
3813 }
3814 
3815 /*****************************************************************************
3816  * IDirectDrawSurface7::UpdateOverlay
3817  *
3818  * Modifies the attributes of an overlay surface.
3819  *
3820  * Params:
3821  * SrcRect: The section of the source being used for the overlay
3822  * DstSurface: Address of the surface that is overlaid
3823  * DstRect: Place of the overlay
3824  * Flags: some DDOVER_* flags
3825  *
3826  * Returns:
3827  * DDERR_UNSUPPORTED, because we don't support overlays
3828  *
3829  *****************************************************************************/
3831  IDirectDrawSurface7 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3832 {
3833  struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface7(iface);
3834  struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface7(dst_surface);
3835  struct wined3d_texture *dst_wined3d_texture = NULL;
3836  unsigned int dst_sub_resource_idx = 0;
3837  HRESULT hr;
3838 
3839  TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3840  iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3841 
3842  if (fx)
3843  FIXME("Ignoring fx %p.\n", fx);
3844 
3846  if (dst_impl)
3847  {
3848  dst_wined3d_texture = dst_impl->wined3d_texture;
3849  dst_sub_resource_idx = dst_impl->sub_resource_idx;
3850  }
3852  src_rect, dst_wined3d_texture, dst_sub_resource_idx, dst_rect, flags);
3854 
3855  switch (hr)
3856  {
3860  default:
3861  return hr;
3862  }
3863 }
3864 
3865 static HRESULT WINAPI ddraw_surface4_UpdateOverlay(IDirectDrawSurface4 *iface, RECT *src_rect,
3866  IDirectDrawSurface4 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3867 {
3868  struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface4(iface);
3869  struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst_surface);
3870 
3871  TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3872  iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3873 
3874  return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3875  dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3876 }
3877 
3878 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect,
3879  IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3880 {
3881  struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface3(iface);
3882  struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface);
3883 
3884  TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3885  iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3886 
3887  return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3888  dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3889 }
3890 
3891 static HRESULT WINAPI ddraw_surface2_UpdateOverlay(IDirectDrawSurface2 *iface, RECT *src_rect,
3892  IDirectDrawSurface2 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3893 {
3894  struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface2(iface);
3895  struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst_surface);
3896 
3897  TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3898  iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3899 
3900  return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3901  dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3902 }
3903 
3904 static HRESULT WINAPI ddraw_surface1_UpdateOverlay(IDirectDrawSurface *iface, RECT *src_rect,
3905  IDirectDrawSurface *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3906 {
3907  struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface(iface);
3908  struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst_surface);
3909 
3910  TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3911  iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3912 
3913  return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3914  dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3915 }
3916 
3917 /*****************************************************************************
3918  * IDirectDrawSurface7::UpdateOverlayDisplay
3919  *
3920  * The DX7 sdk says that it's not implemented
3921  *
3922  * Params:
3923  * Flags: ?
3924  *
3925  * Returns: DDERR_UNSUPPORTED, because we don't support overlays
3926  *
3927  *****************************************************************************/
3929 {
3930  TRACE("iface %p, flags %#x.\n", iface, Flags);
3931 
3932  return DDERR_UNSUPPORTED;
3933 }
3934 
3935 static HRESULT WINAPI ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4 *iface, DWORD flags)
3936 {
3937  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3938 
3939  TRACE("iface %p, flags %#x.\n", iface, flags);
3940 
3942 }
3943 
3944 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags)
3945 {
3946  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3947 
3948  TRACE("iface %p, flags %#x.\n", iface, flags);
3949 
3951 }
3952 
3953 static HRESULT WINAPI ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2 *iface, DWORD flags)
3954 {
3955  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3956 
3957  TRACE("iface %p, flags %#x.\n", iface, flags);
3958 
3960 }
3961 
3963 {
3964  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3965 
3966  TRACE("iface %p, flags %#x.\n", iface, flags);
3967 
3969 }
3970 
3971 /*****************************************************************************
3972  * IDirectDrawSurface7::UpdateOverlayZOrder
3973  *
3974  * Sets an overlay's Z order
3975  *
3976  * Params:
3977  * Flags: DDOVERZ_* flags
3978  * DDSRef: Defines the relative position in the overlay chain
3979  *
3980  * Returns:
3981  * DDERR_NOTOVERLAYSURFACE, because we don't support overlays
3982  *
3983  *****************************************************************************/
3986 {
3987  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3988 
3989  FIXME("iface %p, flags %#x, reference %p stub!\n", iface, flags, reference);
3990 
3992  if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OVERLAY))
3993  {
3994  WARN("Not an overlay surface.\n");
3996  return DDERR_NOTAOVERLAYSURFACE;
3997  }
3999 
4000  return DD_OK;
4001 }
4002 
4003 static HRESULT WINAPI ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4 *iface,
4004  DWORD flags, IDirectDrawSurface4 *reference)
4005 {
4006  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4008 
4009  TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4010 
4012  reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4013 }
4014 
4015 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
4016  DWORD flags, IDirectDrawSurface3 *reference)
4017 {
4018  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4020 
4021  TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4022 
4024  reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4025 }
4026 
4027 static HRESULT WINAPI ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2 *iface,
4028  DWORD flags, IDirectDrawSurface2 *reference)
4029 {
4030  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4032 
4033  TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4034 
4036  reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4037 }
4038 
4039 static HRESULT WINAPI ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface *iface,
4040  DWORD flags, IDirectDrawSurface *reference)
4041 {
4042  struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4044 
4045  TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
4046 
4048  reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
4049 }
4050 
4051 /*****************************************************************************
4052  * IDirectDrawSurface7::GetDDInterface
4053  *
4054  * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
4055  * surface belongs to
4056  *
4057  * Params:
4058  * DD: Address to write the interface pointer to
4059  *
4060  * Returns:
4061  * DD_OK on success
4062  * DDERR_INVALIDPARAMS if DD is NULL
4063  *
4064  *****************************************************************************/
4066 {
4068 
4069  TRACE("iface %p, ddraw %p.\n", iface, DD);
4070 
4071  if(!DD)
4072  return DDERR_INVALIDPARAMS;
4073 
4074  switch(This->version)
4075  {
4076  case 7:
4077  *DD = &This->ddraw->IDirectDraw7_iface;
4078  break;
4079 
4080  case 4:
4081  *DD = &This->ddraw->IDirectDraw4_iface;
4082  break;
4083 
4084  case 2:
4085  *DD = &This->ddraw->IDirectDraw2_iface;
4086  break;
4087 
4088  case 1:
4089  *DD = &This->ddraw->IDirectDraw_iface;
4090  break;
4091 
4092  }
4093  IUnknown_AddRef((IUnknown *)*DD);
4094 
4095  return DD_OK;
4096 }
4097 
4098 static HRESULT WINAPI ddraw_surface4_GetDDInterface(IDirectDrawSurface4 *iface, void **ddraw)
4099 {
4100  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4101 
4102  TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4103 
4105 }
4106 
4107 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw)
4108 {
4109  struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4110 
4111  TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4112 
4114 }
4115 
4116 static HRESULT WINAPI ddraw_surface2_GetDDInterface(IDirectDrawSurface2 *iface, void **ddraw)
4117 {
4118  struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4119 
4120  TRACE("iface %p, ddraw %p.\n", iface, ddraw);
4121 
4123 }
4124 
4126 {
4127  TRACE("iface %p.\n", iface);
4128 
4129  return DD_OK;
4130 }
4131 
4132 static HRESULT WINAPI ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4 *iface)
4133 {
4134  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4135 
4136  TRACE("iface %p.\n", iface);
4137 
4139 }
4140 
4142 {
4143  TRACE("iface %p, value %p.\n", iface, pValue);
4144 
4145  *pValue = 0;
4146 
4147  return DD_OK;
4148 }
4149 
4150 static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *iface, DWORD *pValue)
4151 {
4152  struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4153 
4154  TRACE("iface %p, value %p.\n", iface, pValue);
4155 
4157 }
4158 
4159 /*****************************************************************************
4160  * IDirectDrawSurface7::SetLOD
4161  *
4162  * Sets the level of detail of a texture
4163  *
4164  * Params:
4165  * MaxLOD: LOD to set
4166  *
4167  * Returns:
4168  * DD_OK on success
4169  * DDERR_INVALIDOBJECT if the surface is invalid for this method
4170  *
4171  *****************************************************************************/
4173 {
4174  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4175  HRESULT hr;
4176 
4177  TRACE("iface %p, lod %u.\n", iface, MaxLOD);
4178 
4181  {
4183  return DDERR_INVALIDOBJECT;
4184  }
4185 
4186  hr = wined3d_texture_set_lod(surface->wined3d_texture, MaxLOD);
4188 
4189  return hr;
4190 }
4191 
4192 /*****************************************************************************
4193  * IDirectDrawSurface7::GetLOD
4194  *
4195  * Returns the level of detail of a Direct3D texture
4196  *
4197  * Params:
4198  * MaxLOD: Address to write the LOD to
4199  *
4200  * Returns:
4201  * DD_OK on success
4202  * DDERR_INVALIDPARAMS if MaxLOD is NULL
4203  * DDERR_INVALIDOBJECT if the surface is invalid for this method
4204  *
4205  *****************************************************************************/
4207 {
4208  struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4209 
4210  TRACE("iface %p, lod %p.\n", iface, MaxLOD);
4211 
4212  if(!MaxLOD)
4213  return DDERR_INVALIDPARAMS;
4214 
4217  {
4219  return DDERR_INVALIDOBJECT;
4220  }
4221 
4222  *MaxLOD = wined3d_texture_get_lod(surface->wined3d_texture);
4224 
4225  return DD_OK;
4226 }
4227 
4228 /*****************************************************************************
4229  * IDirectDrawSurface7::BltFast
4230  *
4231  * Performs a fast Blit.
4232  *
4233  * Params:
4234  * dstx: The x coordinate to blit to on the destination
4235  * dsty: The y coordinate to blit to on the destination
4236  * Source: The source surface
4237  * rsrc: The source rectangle
4238  * trans: Type of transfer. Some DDBLTFAST_* flags
4239  *
4240  * Returns:
4241  * DD_OK on success, error code otherwise.
4242  *
4243  *****************************************************************************/
4245  DWORD dst_x, DWORD dst_y, IDirectDrawSurface7 *src_surface, RECT *src_rect, DWORD trans)
4246 {
4247  struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
4248  struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface);
4250  DWORD src_w, src_h, dst_w, dst_h;
4251  HRESULT hr = DD_OK;
4252  RECT dst_rect, s;
4253 
4254  TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4255  iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), trans);
4256 
4257  dst_w = dst_impl->surface_desc.dwWidth;
4258  dst_h = dst_impl->surface_desc.dwHeight;
4259 
4260  if (!src_rect)
4261  {
4262  SetRect(&s, 0, 0, src_impl->surface_desc.dwWidth, src_impl->surface_desc.dwHeight);
4263  src_rect = &s;
4264  }
4265 
4266  src_w = src_rect->right - src_rect->left;
4267  src_h = src_rect->bottom - src_rect->top;
4268  if (src_w > dst_w || dst_x > dst_w - src_w
4269  || src_h > dst_h || dst_y > dst_h - src_h)
4270  {
4271  WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
4272  return DDERR_INVALIDRECT;
4273  }
4274 
4275  SetRect(&dst_rect, dst_x, dst_y, dst_x + src_w, dst_y + src_h);
4276  if (trans & DDBLTFAST_SRCCOLORKEY)
4278  if (trans & DDBLTFAST_DESTCOLORKEY)
4280  if (trans & DDBLTFAST_WAIT)
4282  if (trans & DDBLTFAST_DONOTWAIT)
4284 
4286  if (dst_impl->clipper)
4287  {
4289  WARN("Destination surface has a clipper set, returning DDERR_BLTFASTCANTCLIP.\n");
4290  return DDERR_BLTFASTCANTCLIP;
4291  }
4292 
4294  hr = ddraw_surface_update_frontbuffer(src_impl, src_rect, TRUE);
4295  if (SUCCEEDED(hr))
4296  hr = wined3d_texture_blt(dst_impl->wined3d_texture, dst_impl->sub_resource_idx, &dst_rect,
4297  src_impl->wined3d_texture, src_impl->sub_resource_idx, src_rect, flags, NULL, WINED3D_TEXF_POINT);
4298