[D3D8][D3D9][DDRAW][WINED3D] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / reactos / dll / directx / wine / ddraw / surface.c
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 "ddraw_private.h"
25
26 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface);
27 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface);
28
29 static inline struct ddraw_surface *impl_from_IDirectDrawGammaControl(IDirectDrawGammaControl *iface)
30 {
31 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawGammaControl_iface);
32 }
33
34 /* This is slow, of course. Also, in case of locks, we can't prevent other
35 * applications from drawing to the screen while we've locked the frontbuffer.
36 * We'd like to do this in wined3d instead, but for that to work wined3d needs
37 * to support windowless rendering first. */
38 HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface, const RECT *rect, BOOL read)
39 {
40 HDC surface_dc, screen_dc;
41 int x, y, w, h;
42 HRESULT hr;
43 BOOL ret;
44
45 if (!rect)
46 {
47 x = 0;
48 y = 0;
49 w = surface->surface_desc.dwWidth;
50 h = surface->surface_desc.dwHeight;
51 }
52 else
53 {
54 x = rect->left;
55 y = rect->top;
56 w = rect->right - rect->left;
57 h = rect->bottom - rect->top;
58 }
59
60 if (w <= 0 || h <= 0)
61 return DD_OK;
62
63 if (surface->ddraw->swapchain_window)
64 {
65 /* Nothing to do, we control the frontbuffer, or at least the parts we
66 * care about. */
67 if (read)
68 return DD_OK;
69
70 return wined3d_surface_blt(surface->ddraw->wined3d_frontbuffer, rect,
71 surface->wined3d_surface, rect, 0, NULL, WINED3D_TEXF_POINT);
72 }
73
74 if (FAILED(hr = wined3d_surface_getdc(surface->wined3d_surface, &surface_dc)))
75 {
76 ERR("Failed to get surface DC, hr %#x.\n", hr);
77 return hr;
78 }
79 if (surface->palette)
80 wined3d_palette_apply_to_dc(surface->palette->wineD3DPalette, surface_dc);
81
82 if (!(screen_dc = GetDC(NULL)))
83 {
84 wined3d_surface_releasedc(surface->wined3d_surface, surface_dc);
85 ERR("Failed to get screen DC.\n");
86 return E_FAIL;
87 }
88
89 if (read)
90 ret = BitBlt(surface_dc, x, y, w, h,
91 screen_dc, x, y, SRCCOPY);
92 else
93 ret = BitBlt(screen_dc, x, y, w, h,
94 surface_dc, x, y, SRCCOPY);
95
96 ReleaseDC(NULL, screen_dc);
97 wined3d_surface_releasedc(surface->wined3d_surface, surface_dc);
98
99 if (!ret)
100 {
101 ERR("Failed to blit to/from screen.\n");
102 return E_FAIL;
103 }
104
105 return DD_OK;
106 }
107
108 /*****************************************************************************
109 * IUnknown parts follow
110 *****************************************************************************/
111
112 /*****************************************************************************
113 * IDirectDrawSurface7::QueryInterface
114 *
115 * A normal QueryInterface implementation. For QueryInterface rules
116 * see ddraw.c, IDirectDraw7::QueryInterface. This method
117 * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
118 * in all versions, the IDirectDrawGammaControl interface and it can
119 * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
120 *
121 * Params:
122 * riid: The interface id queried for
123 * obj: Address to write the pointer to
124 *
125 * Returns:
126 * S_OK on success
127 * E_NOINTERFACE if the requested interface wasn't found
128 *
129 *****************************************************************************/
130 static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, REFIID riid, void **obj)
131 {
132 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
133
134 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
135
136 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
137 *obj = NULL;
138
139 if(!riid)
140 return DDERR_INVALIDPARAMS;
141
142 if (IsEqualGUID(riid, &IID_IDirectDrawSurface7))
143 {
144 IDirectDrawSurface7_AddRef(iface);
145 *obj = iface;
146 TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj);
147 return S_OK;
148 }
149
150 if (IsEqualGUID(riid, &IID_IDirectDrawSurface4))
151 {
152 IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface);
153 *obj = &This->IDirectDrawSurface4_iface;
154 TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj);
155 return S_OK;
156 }
157
158 if (IsEqualGUID(riid, &IID_IDirectDrawSurface3))
159 {
160 IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
161 *obj = &This->IDirectDrawSurface3_iface;
162 TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
163 return S_OK;
164 }
165
166 if (IsEqualGUID(riid, &IID_IDirectDrawSurface2))
167 {
168 IDirectDrawSurface2_AddRef(&This->IDirectDrawSurface2_iface);
169 *obj = &This->IDirectDrawSurface2_iface;
170 TRACE("(%p) returning IDirectDrawSurface2 interface at %p\n", This, *obj);
171 return S_OK;
172 }
173
174 if (IsEqualGUID(riid, &IID_IDirectDrawSurface)
175 || IsEqualGUID(riid, &IID_IUnknown))
176 {
177 IDirectDrawSurface_AddRef(&This->IDirectDrawSurface_iface);
178 *obj = &This->IDirectDrawSurface_iface;
179 TRACE("(%p) returning IDirectDrawSurface interface at %p\n", This, *obj);
180 return S_OK;
181 }
182
183 if (IsEqualGUID(riid, &IID_IDirectDrawGammaControl))
184 {
185 IDirectDrawGammaControl_AddRef(&This->IDirectDrawGammaControl_iface);
186 *obj = &This->IDirectDrawGammaControl_iface;
187 TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj);
188 return S_OK;
189 }
190
191 if (IsEqualGUID(riid, &IID_IDirectDrawColorControl))
192 {
193 WARN("Color control not implemented.\n");
194 *obj = NULL;
195 return E_NOINTERFACE;
196 }
197
198 if (This->version != 7)
199 {
200 if (IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D)
201 || IsEqualGUID(riid, &IID_IDirect3DHALDevice)
202 || IsEqualGUID(riid, &IID_IDirect3DRGBDevice))
203 {
204 wined3d_mutex_lock();
205 if (!This->device1)
206 {
207 HRESULT hr;
208
209 if (FAILED(hr = d3d_device_create(This->ddraw, riid, This, (IUnknown *)&This->IDirectDrawSurface_iface,
210 1, &This->device1, (IUnknown *)&This->IDirectDrawSurface_iface)))
211 {
212 This->device1 = NULL;
213 wined3d_mutex_unlock();
214 WARN("Failed to create device, hr %#x.\n", hr);
215 return hr;
216 }
217 }
218 wined3d_mutex_unlock();
219
220 IDirect3DDevice_AddRef(&This->device1->IDirect3DDevice_iface);
221 *obj = &This->device1->IDirect3DDevice_iface;
222 return S_OK;
223 }
224
225 if (IsEqualGUID(&IID_IDirect3DTexture2, riid))
226 {
227 IDirect3DTexture2_AddRef(&This->IDirect3DTexture2_iface);
228 *obj = &This->IDirect3DTexture2_iface;
229 return S_OK;
230 }
231
232 if (IsEqualGUID( &IID_IDirect3DTexture, riid ))
233 {
234 IDirect3DTexture2_AddRef(&This->IDirect3DTexture_iface);
235 *obj = &This->IDirect3DTexture_iface;
236 return S_OK;
237 }
238 }
239
240 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
241
242 if (This->version != 7)
243 return E_INVALIDARG;
244
245 return E_NOINTERFACE;
246 }
247
248 static HRESULT WINAPI ddraw_surface4_QueryInterface(IDirectDrawSurface4 *iface, REFIID riid, void **object)
249 {
250 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
251
252 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
253
254 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
255 }
256
257 static HRESULT WINAPI ddraw_surface3_QueryInterface(IDirectDrawSurface3 *iface, REFIID riid, void **object)
258 {
259 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
260
261 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
262
263 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
264 }
265
266 static HRESULT WINAPI ddraw_surface2_QueryInterface(IDirectDrawSurface2 *iface, REFIID riid, void **object)
267 {
268 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
269
270 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
271
272 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
273 }
274
275 static HRESULT WINAPI ddraw_surface1_QueryInterface(IDirectDrawSurface *iface, REFIID riid, void **object)
276 {
277 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
278
279 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
280
281 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
282 }
283
284 static HRESULT WINAPI ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl *iface,
285 REFIID riid, void **object)
286 {
287 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
288
289 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
290
291 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
292 }
293
294 static HRESULT WINAPI d3d_texture2_QueryInterface(IDirect3DTexture2 *iface, REFIID riid, void **object)
295 {
296 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
297
298 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
299
300 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
301 }
302
303 static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFIID riid, void **object)
304 {
305 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
306
307 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
308
309 return ddraw_surface7_QueryInterface(&surface->IDirectDrawSurface7_iface, riid, object);
310 }
311
312 static void ddraw_surface_add_iface(struct ddraw_surface *surface)
313 {
314 ULONG iface_count = InterlockedIncrement(&surface->iface_count);
315 TRACE("%p increasing iface count to %u.\n", surface, iface_count);
316
317 if (iface_count == 1)
318 {
319 if (surface->ifaceToRelease)
320 IUnknown_AddRef(surface->ifaceToRelease);
321 wined3d_mutex_lock();
322 if (surface->wined3d_rtv)
323 wined3d_rendertarget_view_incref(surface->wined3d_rtv);
324 if (surface->wined3d_surface)
325 wined3d_surface_incref(surface->wined3d_surface);
326 if (surface->wined3d_texture)
327 wined3d_texture_incref(surface->wined3d_texture);
328 wined3d_mutex_unlock();
329 }
330 }
331
332 /*****************************************************************************
333 * IDirectDrawSurface7::AddRef
334 *
335 * A normal addref implementation
336 *
337 * Returns:
338 * The new refcount
339 *
340 *****************************************************************************/
341 static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface)
342 {
343 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
344 ULONG refcount = InterlockedIncrement(&This->ref7);
345
346 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
347
348 if (refcount == 1)
349 {
350 ddraw_surface_add_iface(This);
351 }
352
353 return refcount;
354 }
355
356 static ULONG WINAPI ddraw_surface4_AddRef(IDirectDrawSurface4 *iface)
357 {
358 struct ddraw_surface *This = impl_from_IDirectDrawSurface4(iface);
359 ULONG refcount = InterlockedIncrement(&This->ref4);
360
361 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
362
363 if (refcount == 1)
364 {
365 ddraw_surface_add_iface(This);
366 }
367
368 return refcount;
369 }
370
371 static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface)
372 {
373 struct ddraw_surface *This = impl_from_IDirectDrawSurface3(iface);
374 ULONG refcount = InterlockedIncrement(&This->ref3);
375
376 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
377
378 if (refcount == 1)
379 {
380 ddraw_surface_add_iface(This);
381 }
382
383 return refcount;
384 }
385
386 static ULONG WINAPI ddraw_surface2_AddRef(IDirectDrawSurface2 *iface)
387 {
388 struct ddraw_surface *This = impl_from_IDirectDrawSurface2(iface);
389 ULONG refcount = InterlockedIncrement(&This->ref2);
390
391 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
392
393 if (refcount == 1)
394 {
395 ddraw_surface_add_iface(This);
396 }
397
398 return refcount;
399 }
400
401 static ULONG WINAPI ddraw_surface1_AddRef(IDirectDrawSurface *iface)
402 {
403 struct ddraw_surface *This = impl_from_IDirectDrawSurface(iface);
404 ULONG refcount = InterlockedIncrement(&This->ref1);
405
406 TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
407
408 if (refcount == 1)
409 {
410 ddraw_surface_add_iface(This);
411 }
412
413 return refcount;
414 }
415
416 static ULONG WINAPI ddraw_gamma_control_AddRef(IDirectDrawGammaControl *iface)
417 {
418 struct ddraw_surface *This = impl_from_IDirectDrawGammaControl(iface);
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 {
425 ddraw_surface_add_iface(This);
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 {
451 struct ddraw_palette *palette_impl = unsafe_impl_from_IDirectDrawPalette(palette);
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");
460 return DDERR_INVALIDSURFACETYPE;
461 }
462
463 if (!format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat))
464 return DDERR_INVALIDPIXELFORMAT;
465
466 wined3d_mutex_lock();
467
468 prev = surface->palette;
469 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
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->wineD3DPalette : NULL);
477 ddraw_surface_update_frontbuffer(surface, NULL, FALSE);
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
485 wined3d_mutex_unlock();
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. */
499 ddraw_surface_set_palette(surface, NULL);
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)
529 wined3d_rendertarget_view_decref(surface->wined3d_rtv);
530 if (surface->wined3d_texture)
531 wined3d_texture_decref(surface->wined3d_texture);
532 if (surface->wined3d_surface)
533 wined3d_surface_decref(surface->wined3d_surface);
534 }
535
536 ULONG ddraw_surface_release_iface(struct ddraw_surface *This)
537 {
538 ULONG iface_count = InterlockedDecrement(&This->iface_count);
539 TRACE("%p decreasing iface count to %u.\n", This, iface_count);
540
541 if (iface_count == 0)
542 {
543 IUnknown *release_iface = This->ifaceToRelease;
544
545 /* Complex attached surfaces are destroyed implicitly when the root is released */
546 wined3d_mutex_lock();
547 if(!This->is_complex_root)
548 {
549 WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
550 wined3d_mutex_unlock();
551 return iface_count;
552 }
553 ddraw_surface_cleanup(This);
554 wined3d_mutex_unlock();
555
556 if (release_iface)
557 IUnknown_Release(release_iface);
558 }
559
560 return iface_count;
561 }
562
563 /*****************************************************************************
564 * IDirectDrawSurface7::Release
565 *
566 * Reduces the surface's refcount by 1. If the refcount falls to 0, the
567 * surface is destroyed.
568 *
569 * Destroying the surface is a bit tricky. For the connection between
570 * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
571 * It has a nice graph explaining the connection.
572 *
573 * What happens here is basically this:
574 * When a surface is destroyed, its WineD3DSurface is released,
575 * and the refcount of the DirectDraw interface is reduced by 1. If it has
576 * complex surfaces attached to it, then these surfaces are destroyed too,
577 * regardless of their refcount. If any surface being destroyed has another
578 * surface attached to it (with a "soft" attachment, not complex), then
579 * this surface is detached with DeleteAttachedSurface.
580 *
581 * When the surface is a texture, the WineD3DTexture is released.
582 * If the surface is the Direct3D render target, then the D3D
583 * capabilities of the WineD3DDevice are uninitialized, which causes the
584 * swapchain to be released.
585 *
586 * When a complex sublevel falls to ref zero, then this is ignored.
587 *
588 * Returns:
589 * The new refcount
590 *
591 *****************************************************************************/
592 static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface)
593 {
594 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
595 ULONG refcount = InterlockedDecrement(&This->ref7);
596
597 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
598
599 if (refcount == 0)
600 {
601 ddraw_surface_release_iface(This);
602 }
603
604 return refcount;
605 }
606
607 static ULONG WINAPI ddraw_surface4_Release(IDirectDrawSurface4 *iface)
608 {
609 struct ddraw_surface *This = impl_from_IDirectDrawSurface4(iface);
610 ULONG refcount = InterlockedDecrement(&This->ref4);
611
612 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
613
614 if (refcount == 0)
615 {
616 ddraw_surface_release_iface(This);
617 }
618
619 return refcount;
620 }
621
622 static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface)
623 {
624 struct ddraw_surface *This = impl_from_IDirectDrawSurface3(iface);
625 ULONG refcount = InterlockedDecrement(&This->ref3);
626
627 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
628
629 if (refcount == 0)
630 {
631 ddraw_surface_release_iface(This);
632 }
633
634 return refcount;
635 }
636
637 static ULONG WINAPI ddraw_surface2_Release(IDirectDrawSurface2 *iface)
638 {
639 struct ddraw_surface *This = impl_from_IDirectDrawSurface2(iface);
640 ULONG refcount = InterlockedDecrement(&This->ref2);
641
642 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
643
644 if (refcount == 0)
645 {
646 ddraw_surface_release_iface(This);
647 }
648
649 return refcount;
650 }
651
652 static ULONG WINAPI ddraw_surface1_Release(IDirectDrawSurface *iface)
653 {
654 struct ddraw_surface *This = impl_from_IDirectDrawSurface(iface);
655 ULONG refcount = InterlockedDecrement(&This->ref1);
656
657 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
658
659 if (refcount == 0)
660 {
661 ddraw_surface_release_iface(This);
662 }
663
664 return refcount;
665 }
666
667 static ULONG WINAPI ddraw_gamma_control_Release(IDirectDrawGammaControl *iface)
668 {
669 struct ddraw_surface *This = impl_from_IDirectDrawGammaControl(iface);
670 ULONG refcount = InterlockedDecrement(&This->gamma_count);
671
672 TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
673
674 if (refcount == 0)
675 {
676 ddraw_surface_release_iface(This);
677 }
678
679 return refcount;
680 }
681
682 static ULONG WINAPI d3d_texture2_Release(IDirect3DTexture2 *iface)
683 {
684 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
685
686 TRACE("iface %p.\n", iface);
687
688 return IUnknown_Release(surface->texture_outer);
689 }
690
691 static ULONG WINAPI d3d_texture1_Release(IDirect3DTexture *iface)
692 {
693 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
694
695 TRACE("iface %p.\n", iface);
696
697 return IUnknown_Release(surface->texture_outer);
698 }
699
700 /*****************************************************************************
701 * IDirectDrawSurface7::GetAttachedSurface
702 *
703 * Returns an attached surface with the requested caps. Surface attachment
704 * and complex surfaces are not clearly described by the MSDN or sdk,
705 * so this method is tricky and likely to contain problems.
706 * This implementation searches the complex list first, then the
707 * attachment chain.
708 *
709 * The chains are searched from This down to the last surface in the chain,
710 * not from the first element in the chain. The first surface found is
711 * returned. The MSDN says that this method fails if more than one surface
712 * matches the caps, but it is not sure if that is right. The attachment
713 * structure may not even allow two matching surfaces.
714 *
715 * The found surface is AddRef-ed before it is returned.
716 *
717 * Params:
718 * Caps: Pointer to a DDCAPS2 structure describing the caps asked for
719 * Surface: Address to store the found surface
720 *
721 * Returns:
722 * DD_OK on success
723 * DDERR_INVALIDPARAMS if Caps or Surface is NULL
724 * DDERR_NOTFOUND if no surface was found
725 *
726 *****************************************************************************/
727 static HRESULT WINAPI ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7 *iface,
728 DDSCAPS2 *Caps, IDirectDrawSurface7 **Surface)
729 {
730 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
731 struct ddraw_surface *surf;
732 DDSCAPS2 our_caps;
733 int i;
734
735 TRACE("iface %p, caps %p, attachment %p.\n", iface, Caps, Surface);
736
737 wined3d_mutex_lock();
738
739 if(This->version < 7)
740 {
741 /* Earlier dx apps put garbage into these members, clear them */
742 our_caps.dwCaps = Caps->dwCaps;
743 our_caps.dwCaps2 = 0;
744 our_caps.dwCaps3 = 0;
745 our_caps.u1.dwCaps4 = 0;
746 }
747 else
748 {
749 our_caps = *Caps;
750 }
751
752 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 */
753
754 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
755 {
756 surf = This->complex_array[i];
757 if(!surf) break;
758
759 TRACE("Surface: (%p) caps: %#x, %#x, %#x, %#x.\n", surf,
760 surf->surface_desc.ddsCaps.dwCaps,
761 surf->surface_desc.ddsCaps.dwCaps2,
762 surf->surface_desc.ddsCaps.dwCaps3,
763 surf->surface_desc.ddsCaps.u1.dwCaps4);
764
765 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
766 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
767
768 /* MSDN: "This method fails if more than one surface is attached
769 * that matches the capabilities requested."
770 *
771 * Not sure how to test this.
772 */
773
774 TRACE("(%p): Returning surface %p\n", This, surf);
775 *Surface = &surf->IDirectDrawSurface7_iface;
776 ddraw_surface7_AddRef(*Surface);
777 wined3d_mutex_unlock();
778
779 return DD_OK;
780 }
781 }
782
783 /* Next, look at the attachment chain */
784 surf = This;
785
786 while( (surf = surf->next_attached) )
787 {
788 TRACE("Surface: (%p) caps: %#x, %#x, %#x, %#x.\n", surf,
789 surf->surface_desc.ddsCaps.dwCaps,
790 surf->surface_desc.ddsCaps.dwCaps2,
791 surf->surface_desc.ddsCaps.dwCaps3,
792 surf->surface_desc.ddsCaps.u1.dwCaps4);
793
794 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
795 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
796
797 TRACE("(%p): Returning surface %p\n", This, surf);
798 *Surface = &surf->IDirectDrawSurface7_iface;
799 ddraw_surface7_AddRef(*Surface);
800 wined3d_mutex_unlock();
801 return DD_OK;
802 }
803 }
804
805 TRACE("(%p) Didn't find a valid surface\n", This);
806
807 wined3d_mutex_unlock();
808
809 *Surface = NULL;
810 return DDERR_NOTFOUND;
811 }
812
813 static HRESULT WINAPI ddraw_surface4_GetAttachedSurface(IDirectDrawSurface4 *iface,
814 DDSCAPS2 *caps, IDirectDrawSurface4 **attachment)
815 {
816 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
817 struct ddraw_surface *attachment_impl;
818 IDirectDrawSurface7 *attachment7;
819 HRESULT hr;
820
821 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
822
823 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
824 caps, &attachment7);
825 if (FAILED(hr))
826 {
827 *attachment = NULL;
828 return hr;
829 }
830 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
831 *attachment = &attachment_impl->IDirectDrawSurface4_iface;
832 ddraw_surface4_AddRef(*attachment);
833 ddraw_surface7_Release(attachment7);
834
835 return hr;
836 }
837
838 static HRESULT WINAPI ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3 *iface,
839 DDSCAPS *caps, IDirectDrawSurface3 **attachment)
840 {
841 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
842 struct ddraw_surface *attachment_impl;
843 IDirectDrawSurface7 *attachment7;
844 DDSCAPS2 caps2;
845 HRESULT hr;
846
847 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
848
849 caps2.dwCaps = caps->dwCaps;
850 caps2.dwCaps2 = 0;
851 caps2.dwCaps3 = 0;
852 caps2.u1.dwCaps4 = 0;
853
854 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
855 &caps2, &attachment7);
856 if (FAILED(hr))
857 {
858 *attachment = NULL;
859 return hr;
860 }
861 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
862 *attachment = &attachment_impl->IDirectDrawSurface3_iface;
863 ddraw_surface3_AddRef(*attachment);
864 ddraw_surface7_Release(attachment7);
865
866 return hr;
867 }
868
869 static HRESULT WINAPI ddraw_surface2_GetAttachedSurface(IDirectDrawSurface2 *iface,
870 DDSCAPS *caps, IDirectDrawSurface2 **attachment)
871 {
872 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
873 struct ddraw_surface *attachment_impl;
874 IDirectDrawSurface7 *attachment7;
875 DDSCAPS2 caps2;
876 HRESULT hr;
877
878 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
879
880 caps2.dwCaps = caps->dwCaps;
881 caps2.dwCaps2 = 0;
882 caps2.dwCaps3 = 0;
883 caps2.u1.dwCaps4 = 0;
884
885 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
886 &caps2, &attachment7);
887 if (FAILED(hr))
888 {
889 *attachment = NULL;
890 return hr;
891 }
892 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
893 *attachment = &attachment_impl->IDirectDrawSurface2_iface;
894 ddraw_surface2_AddRef(*attachment);
895 ddraw_surface7_Release(attachment7);
896
897 return hr;
898 }
899
900 static HRESULT WINAPI ddraw_surface1_GetAttachedSurface(IDirectDrawSurface *iface,
901 DDSCAPS *caps, IDirectDrawSurface **attachment)
902 {
903 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
904 struct ddraw_surface *attachment_impl;
905 IDirectDrawSurface7 *attachment7;
906 DDSCAPS2 caps2;
907 HRESULT hr;
908
909 TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
910
911 caps2.dwCaps = caps->dwCaps;
912 caps2.dwCaps2 = 0;
913 caps2.dwCaps3 = 0;
914 caps2.u1.dwCaps4 = 0;
915
916 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface,
917 &caps2, &attachment7);
918 if (FAILED(hr))
919 {
920 *attachment = NULL;
921 return hr;
922 }
923 attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
924 *attachment = &attachment_impl->IDirectDrawSurface_iface;
925 ddraw_surface1_AddRef(*attachment);
926 ddraw_surface7_Release(attachment7);
927
928 return hr;
929 }
930
931 /*****************************************************************************
932 * IDirectDrawSurface7::Lock
933 *
934 * Locks the surface and returns a pointer to the surface's memory
935 *
936 * Params:
937 * Rect: Rectangle to lock. If NULL, the whole surface is locked
938 * DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
939 * Flags: Locking flags, e.g Read only or write only
940 * h: An event handle that's not used and must be NULL
941 *
942 * Returns:
943 * DD_OK on success
944 * DDERR_INVALIDPARAMS if DDSD is NULL
945 * For more details, see IWineD3DSurface::LockRect
946 *
947 *****************************************************************************/
948 static HRESULT surface_lock(struct ddraw_surface *This,
949 RECT *Rect, DDSURFACEDESC2 *DDSD, DWORD Flags, HANDLE h)
950 {
951 struct wined3d_box box;
952 struct wined3d_map_desc map_desc;
953 HRESULT hr = DD_OK;
954
955 TRACE("This %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
956 This, wine_dbgstr_rect(Rect), DDSD, Flags, h);
957
958 /* This->surface_desc.dwWidth and dwHeight are changeable, thus lock */
959 wined3d_mutex_lock();
960
961 /* Should I check for the handle to be NULL?
962 *
963 * The DDLOCK flags and the D3DLOCK flags are equal
964 * for the supported values. The others are ignored by WineD3D
965 */
966
967 /* Windows zeroes this if the rect is invalid */
968 DDSD->lpSurface = 0;
969
970 if (Rect)
971 {
972 if ((Rect->left < 0)
973 || (Rect->top < 0)
974 || (Rect->left > Rect->right)
975 || (Rect->top > Rect->bottom)
976 || (Rect->right > This->surface_desc.dwWidth)
977 || (Rect->bottom > This->surface_desc.dwHeight))
978 {
979 WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
980 wined3d_mutex_unlock();
981 return DDERR_INVALIDPARAMS;
982 }
983 box.left = Rect->left;
984 box.top = Rect->top;
985 box.right = Rect->right;
986 box.bottom = Rect->bottom;
987 box.front = 0;
988 box.back = 1;
989 }
990
991 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
992 hr = ddraw_surface_update_frontbuffer(This, Rect, TRUE);
993 if (SUCCEEDED(hr))
994 hr = wined3d_surface_map(This->wined3d_surface, &map_desc, Rect ? &box : NULL, Flags);
995 if (FAILED(hr))
996 {
997 wined3d_mutex_unlock();
998 switch(hr)
999 {
1000 /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
1001 * specific error. But since IWineD3DSurface::LockRect returns that error in this
1002 * only occasion, keep d3d8 and d3d9 free from the return value override. There are
1003 * many different places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it
1004 * is much easier to do it in one place in ddraw
1005 */
1006 case WINED3DERR_INVALIDCALL: return DDERR_SURFACEBUSY;
1007 default: return hr;
1008 }
1009 }
1010
1011 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1012 {
1013 if (Flags & DDLOCK_READONLY)
1014 memset(&This->ddraw->primary_lock, 0, sizeof(This->ddraw->primary_lock));
1015 else if (Rect)
1016 This->ddraw->primary_lock = *Rect;
1017 else
1018 SetRect(&This->ddraw->primary_lock, 0, 0, This->surface_desc.dwWidth, This->surface_desc.dwHeight);
1019 }
1020
1021 /* Windows does not set DDSD_LPSURFACE on locked surfaces. */
1022 DD_STRUCT_COPY_BYSIZE(DDSD,&(This->surface_desc));
1023 DDSD->lpSurface = map_desc.data;
1024
1025 TRACE("locked surface returning description :\n");
1026 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
1027
1028 wined3d_mutex_unlock();
1029
1030 return DD_OK;
1031 }
1032
1033 static HRESULT WINAPI ddraw_surface7_Lock(IDirectDrawSurface7 *iface,
1034 RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
1035 {
1036 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1037
1038 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1039 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1040
1041 if (!surface_desc) return DDERR_INVALIDPARAMS;
1042 if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1043 surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1044 {
1045 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1046 return DDERR_INVALIDPARAMS;
1047 }
1048 return surface_lock(surface, rect, surface_desc, flags, h);
1049 }
1050
1051 static HRESULT WINAPI ddraw_surface4_Lock(IDirectDrawSurface4 *iface, RECT *rect,
1052 DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
1053 {
1054 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1055
1056 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1057 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1058
1059 if (!surface_desc) return DDERR_INVALIDPARAMS;
1060 if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1061 surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1062 {
1063 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1064 return DDERR_INVALIDPARAMS;
1065 }
1066 return surface_lock(surface, rect, surface_desc, flags, h);
1067 }
1068
1069 static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect,
1070 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1071 {
1072 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1073 DDSURFACEDESC2 surface_desc2;
1074 HRESULT hr;
1075
1076 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1077 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1078
1079 if (!surface_desc) return DDERR_INVALIDPARAMS;
1080 if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1081 surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1082 {
1083 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1084 return DDERR_INVALIDPARAMS;
1085 }
1086
1087 surface_desc2.dwSize = surface_desc->dwSize;
1088 surface_desc2.dwFlags = 0;
1089 hr = surface_lock(surface, rect, &surface_desc2, flags, h);
1090 DDSD2_to_DDSD(&surface_desc2, surface_desc);
1091 surface_desc->dwSize = surface_desc2.dwSize;
1092 return hr;
1093 }
1094
1095 static HRESULT WINAPI ddraw_surface2_Lock(IDirectDrawSurface2 *iface, RECT *rect,
1096 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1097 {
1098 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1099 DDSURFACEDESC2 surface_desc2;
1100 HRESULT hr;
1101
1102 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1103 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1104
1105 if (!surface_desc) return DDERR_INVALIDPARAMS;
1106 if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1107 surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1108 {
1109 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1110 return DDERR_INVALIDPARAMS;
1111 }
1112
1113 surface_desc2.dwSize = surface_desc->dwSize;
1114 surface_desc2.dwFlags = 0;
1115 hr = surface_lock(surface, rect, &surface_desc2, flags, h);
1116 DDSD2_to_DDSD(&surface_desc2, surface_desc);
1117 surface_desc->dwSize = surface_desc2.dwSize;
1118 return hr;
1119 }
1120
1121 static HRESULT WINAPI ddraw_surface1_Lock(IDirectDrawSurface *iface, RECT *rect,
1122 DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1123 {
1124 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1125 DDSURFACEDESC2 surface_desc2;
1126 HRESULT hr;
1127 TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1128 iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1129
1130 if (!surface_desc) return DDERR_INVALIDPARAMS;
1131 if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1132 surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1133 {
1134 WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1135 return DDERR_INVALIDPARAMS;
1136 }
1137
1138 surface_desc2.dwSize = surface_desc->dwSize;
1139 surface_desc2.dwFlags = 0;
1140 hr = surface_lock(surface, rect, &surface_desc2, flags, h);
1141 DDSD2_to_DDSD(&surface_desc2, surface_desc);
1142 surface_desc->dwSize = surface_desc2.dwSize;
1143 return hr;
1144 }
1145
1146 /*****************************************************************************
1147 * IDirectDrawSurface7::Unlock
1148 *
1149 * Unlocks an locked surface
1150 *
1151 * Params:
1152 * Rect: Not used by this implementation
1153 *
1154 * Returns:
1155 * D3D_OK on success
1156 * For more details, see IWineD3DSurface::UnlockRect
1157 *
1158 *****************************************************************************/
1159 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *pRect)
1160 {
1161 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1162 HRESULT hr;
1163
1164 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(pRect));
1165
1166 wined3d_mutex_lock();
1167 hr = wined3d_surface_unmap(surface->wined3d_surface);
1168 if (SUCCEEDED(hr) && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1169 hr = ddraw_surface_update_frontbuffer(surface, &surface->ddraw->primary_lock, FALSE);
1170 wined3d_mutex_unlock();
1171
1172 return hr;
1173 }
1174
1175 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Unlock(IDirectDrawSurface4 *iface, RECT *pRect)
1176 {
1177 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1178
1179 TRACE("iface %p, rect %p.\n", iface, pRect);
1180
1181 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, pRect);
1182 }
1183
1184 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Unlock(IDirectDrawSurface3 *iface, void *data)
1185 {
1186 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1187
1188 TRACE("iface %p, data %p.\n", iface, data);
1189
1190 /* data might not be the LPRECT of later versions, so drop it. */
1191 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL);
1192 }
1193
1194 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Unlock(IDirectDrawSurface2 *iface, void *data)
1195 {
1196 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1197
1198 TRACE("iface %p, data %p.\n", iface, data);
1199
1200 /* data might not be the LPRECT of later versions, so drop it. */
1201 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL);
1202 }
1203
1204 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Unlock(IDirectDrawSurface *iface, void *data)
1205 {
1206 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1207
1208 TRACE("iface %p, data %p.\n", iface, data);
1209
1210 /* data might not be the LPRECT of later versions, so drop it. */
1211 return ddraw_surface7_Unlock(&surface->IDirectDrawSurface7_iface, NULL);
1212 }
1213
1214 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Flip(IDirectDrawSurface7 *iface,
1215 IDirectDrawSurface7 *src, DWORD flags)
1216 {
1217 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface);
1218 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src);
1219 struct wined3d_rendertarget_view *tmp_rtv, *src_rtv, *rtv;
1220 struct ddraw_texture *ddraw_texture, *prev_ddraw_texture;
1221 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
1222 struct wined3d_texture *texture;
1223 IDirectDrawSurface7 *current;
1224 struct wined3d_surface *tmp;
1225 HRESULT hr;
1226
1227 TRACE("iface %p, src %p, flags %#x.\n", iface, src, flags);
1228
1229 if (src == iface || !(dst_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)))
1230 return DDERR_NOTFLIPPABLE;
1231
1232 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
1233 return DDERR_SURFACELOST;
1234
1235 wined3d_mutex_lock();
1236
1237 tmp_rtv = ddraw_surface_get_rendertarget_view(dst_impl);
1238 tmp = dst_impl->wined3d_surface;
1239 texture = dst_impl->wined3d_texture;
1240 rtv = wined3d_device_get_rendertarget_view(dst_impl->ddraw->wined3d_device, 0);
1241 ddraw_texture = wined3d_texture_get_parent(dst_impl->wined3d_texture);
1242
1243 if (src_impl)
1244 {
1245 for (current = iface; current != src;)
1246 {
1247 if (FAILED(hr = ddraw_surface7_GetAttachedSurface(current, &caps, &current)))
1248 {
1249 WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
1250 wined3d_mutex_unlock();
1251 return DDERR_NOTFLIPPABLE;
1252 }
1253 ddraw_surface7_Release(current);
1254 if (current == iface)
1255 {
1256 WARN("Surface %p is not on the same flip chain as surface %p.\n", src, iface);
1257 wined3d_mutex_unlock();
1258 return DDERR_NOTFLIPPABLE;
1259 }
1260 }
1261
1262 src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
1263 if (rtv == dst_impl->wined3d_rtv)
1264 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
1265 wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
1266 dst_impl->wined3d_rtv = src_rtv;
1267 wined3d_resource_set_parent(wined3d_surface_get_resource(src_impl->wined3d_surface), dst_impl);
1268 dst_impl->wined3d_surface = src_impl->wined3d_surface;
1269 prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
1270 wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), ddraw_texture);
1271 dst_impl->wined3d_texture = src_impl->wined3d_texture;
1272 ddraw_texture = prev_ddraw_texture;
1273 }
1274 else
1275 {
1276 for (current = iface;;)
1277 {
1278 if (FAILED(hr = ddraw_surface7_GetAttachedSurface(current, &caps, &current)))
1279 {
1280 ERR("Can't find a flip target\n");
1281 wined3d_mutex_unlock();
1282 return DDERR_NOTFLIPPABLE; /* Unchecked */
1283 }
1284 ddraw_surface7_Release(current);
1285 if (current == iface)
1286 {
1287 dst_impl = impl_from_IDirectDrawSurface7(iface);
1288 break;
1289 }
1290
1291 src_impl = impl_from_IDirectDrawSurface7(current);
1292 src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
1293 if (rtv == dst_impl->wined3d_rtv)
1294 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, src_rtv, FALSE);
1295 wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
1296 dst_impl->wined3d_rtv = src_rtv;
1297 wined3d_resource_set_parent(wined3d_surface_get_resource(src_impl->wined3d_surface), dst_impl);
1298 dst_impl->wined3d_surface = src_impl->wined3d_surface;
1299 prev_ddraw_texture = wined3d_texture_get_parent(src_impl->wined3d_texture);
1300 wined3d_resource_set_parent(wined3d_texture_get_resource(src_impl->wined3d_texture), ddraw_texture);
1301 ddraw_texture = prev_ddraw_texture;
1302 dst_impl->wined3d_texture = src_impl->wined3d_texture;
1303 dst_impl = src_impl;
1304 }
1305 }
1306
1307 /* We don't have to worry about potential texture bindings, since
1308 * flippable surfaces can never be textures. */
1309 if (rtv == src_impl->wined3d_rtv)
1310 wined3d_device_set_rendertarget_view(dst_impl->ddraw->wined3d_device, 0, tmp_rtv, FALSE);
1311 wined3d_rendertarget_view_set_parent(tmp_rtv, src_impl);
1312 src_impl->wined3d_rtv = tmp_rtv;
1313 wined3d_resource_set_parent(wined3d_surface_get_resource(tmp), src_impl);
1314 src_impl->wined3d_surface = tmp;
1315 wined3d_resource_set_parent(wined3d_texture_get_resource(texture), ddraw_texture);
1316 src_impl->wined3d_texture = texture;
1317
1318 if (flags)
1319 {
1320 static UINT once;
1321 if (!once++)
1322 FIXME("Ignoring flags %#x.\n", flags);
1323 else
1324 WARN("Ignoring flags %#x.\n", flags);
1325 }
1326
1327 if (dst_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1328 hr = ddraw_surface_update_frontbuffer(dst_impl, NULL, FALSE);
1329 else
1330 hr = DD_OK;
1331
1332 wined3d_mutex_unlock();
1333
1334 return hr;
1335 }
1336
1337 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Flip(IDirectDrawSurface4 *iface,
1338 IDirectDrawSurface4 *dst, DWORD flags)
1339 {
1340 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1341 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst);
1342
1343 TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1344
1345 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface,
1346 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1347 }
1348
1349 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Flip(IDirectDrawSurface3 *iface,
1350 IDirectDrawSurface3 *dst, DWORD flags)
1351 {
1352 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1353 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst);
1354
1355 TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1356
1357 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface,
1358 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1359 }
1360
1361 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Flip(IDirectDrawSurface2 *iface,
1362 IDirectDrawSurface2 *dst, DWORD flags)
1363 {
1364 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1365 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst);
1366
1367 TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1368
1369 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface,
1370 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1371 }
1372
1373 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *iface,
1374 IDirectDrawSurface *dst, DWORD flags)
1375 {
1376 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1377 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst);
1378
1379 TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1380
1381 return ddraw_surface7_Flip(&surface->IDirectDrawSurface7_iface,
1382 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1383 }
1384
1385 static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, const RECT *dst_rect_in,
1386 struct ddraw_surface *src_surface, const RECT *src_rect_in, DWORD flags,
1387 const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter)
1388 {
1389 struct wined3d_surface *wined3d_src_surface = src_surface ? src_surface->wined3d_surface : NULL;
1390 RECT src_rect, dst_rect;
1391 float scale_x, scale_y;
1392 const RECT *clip_rect;
1393 UINT clip_list_size;
1394 RGNDATA *clip_list;
1395 HRESULT hr = DD_OK;
1396 UINT i;
1397
1398 if (!dst_surface->clipper)
1399 {
1400 if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1401 hr = ddraw_surface_update_frontbuffer(src_surface, src_rect_in, TRUE);
1402 if (SUCCEEDED(hr))
1403 hr = wined3d_surface_blt(dst_surface->wined3d_surface, dst_rect_in,
1404 wined3d_src_surface, src_rect_in, flags, fx, filter);
1405 if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
1406 hr = ddraw_surface_update_frontbuffer(dst_surface, dst_rect_in, FALSE);
1407
1408 return hr;
1409 }
1410
1411 if (!dst_rect_in)
1412 {
1413 dst_rect.left = 0;
1414 dst_rect.top = 0;
1415 dst_rect.right = dst_surface->surface_desc.dwWidth;
1416 dst_rect.bottom = dst_surface->surface_desc.dwHeight;
1417 }
1418 else
1419 {
1420 dst_rect = *dst_rect_in;
1421 }
1422
1423 if (IsRectEmpty(&dst_rect))
1424 return DDERR_INVALIDRECT;
1425
1426 if (src_surface)
1427 {
1428 if (!src_rect_in)
1429 {
1430 src_rect.left = 0;
1431 src_rect.top = 0;
1432 src_rect.right = src_surface->surface_desc.dwWidth;
1433 src_rect.bottom = src_surface->surface_desc.dwHeight;
1434 }
1435 else
1436 {
1437 src_rect = *src_rect_in;
1438 }
1439
1440 if (IsRectEmpty(&src_rect))
1441 return DDERR_INVALIDRECT;
1442 }
1443 else
1444 {
1445 SetRect(&src_rect, 0, 0, 0, 0);
1446 }
1447
1448 scale_x = (float)(src_rect.right - src_rect.left) / (float)(dst_rect.right - dst_rect.left);
1449 scale_y = (float)(src_rect.bottom - src_rect.top) / (float)(dst_rect.bottom - dst_rect.top);
1450
1451 if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
1452 &dst_rect, NULL, &clip_list_size)))
1453 {
1454 WARN("Failed to get clip list size, hr %#x.\n", hr);
1455 return hr;
1456 }
1457
1458 if (!(clip_list = HeapAlloc(GetProcessHeap(), 0, clip_list_size)))
1459 {
1460 WARN("Failed to allocate clip list.\n");
1461 return E_OUTOFMEMORY;
1462 }
1463
1464 if (FAILED(hr = IDirectDrawClipper_GetClipList(&dst_surface->clipper->IDirectDrawClipper_iface,
1465 &dst_rect, clip_list, &clip_list_size)))
1466 {
1467 WARN("Failed to get clip list, hr %#x.\n", hr);
1468 HeapFree(GetProcessHeap(), 0, clip_list);
1469 return hr;
1470 }
1471
1472 clip_rect = (RECT *)clip_list->Buffer;
1473 for (i = 0; i < clip_list->rdh.nCount; ++i)
1474 {
1475 RECT src_rect_clipped = src_rect;
1476
1477 if (src_surface)
1478 {
1479 src_rect_clipped.left += (LONG)((clip_rect[i].left - dst_rect.left) * scale_x);
1480 src_rect_clipped.top += (LONG)((clip_rect[i].top - dst_rect.top) * scale_y);
1481 src_rect_clipped.right -= (LONG)((dst_rect.right - clip_rect[i].right) * scale_x);
1482 src_rect_clipped.bottom -= (LONG)((dst_rect.bottom - clip_rect[i].bottom) * scale_y);
1483
1484 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1485 {
1486 if (FAILED(hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect_clipped, TRUE)))
1487 break;
1488 }
1489 }
1490
1491 if (FAILED(hr = wined3d_surface_blt(dst_surface->wined3d_surface, &clip_rect[i],
1492 wined3d_src_surface, &src_rect_clipped, flags, fx, filter)))
1493 break;
1494
1495 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1496 {
1497 if (FAILED(hr = ddraw_surface_update_frontbuffer(dst_surface, &clip_rect[i], FALSE)))
1498 break;
1499 }
1500 }
1501
1502 HeapFree(GetProcessHeap(), 0, clip_list);
1503 return hr;
1504 }
1505
1506 /*****************************************************************************
1507 * IDirectDrawSurface7::Blt
1508 *
1509 * Performs a blit on the surface
1510 *
1511 * Params:
1512 * DestRect: Destination rectangle, can be NULL
1513 * SrcSurface: Source surface, can be NULL
1514 * SrcRect: Source rectangle, can be NULL
1515 * Flags: Blt flags
1516 * DDBltFx: Some extended blt parameters, connected to the flags
1517 *
1518 * Returns:
1519 * D3D_OK on success
1520 * See IWineD3DSurface::Blt for more details
1521 *
1522 *****************************************************************************/
1523 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *DestRect,
1524 IDirectDrawSurface7 *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx)
1525 {
1526 struct ddraw_surface *dst_surface = impl_from_IDirectDrawSurface7(iface);
1527 struct ddraw_surface *src_surface = unsafe_impl_from_IDirectDrawSurface7(SrcSurface);
1528 HRESULT hr = DD_OK;
1529 DDBLTFX rop_fx;
1530
1531 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1532 iface, wine_dbgstr_rect(DestRect), SrcSurface, wine_dbgstr_rect(SrcRect), Flags, DDBltFx);
1533
1534 /* Check for validity of the flags here. WineD3D Has the software-opengl selection path and would have
1535 * to check at 2 places, and sometimes do double checks. This also saves the call to wined3d :-)
1536 */
1537 if((Flags & DDBLT_KEYSRCOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYSRC)) {
1538 WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
1539 return DDERR_INVALIDPARAMS;
1540 }
1541
1542 if((Flags & DDBLT_KEYDESTOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYDEST)) {
1543 WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
1544 return DDERR_INVALIDPARAMS;
1545 }
1546
1547 wined3d_mutex_lock();
1548
1549 if (Flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL))
1550 {
1551 if (Flags & DDBLT_ROP)
1552 {
1553 wined3d_mutex_unlock();
1554 WARN("DDBLT_ROP used with DDBLT_COLORFILL or DDBLT_DEPTHFILL, returning DDERR_INVALIDPARAMS.\n");
1555 return DDERR_INVALIDPARAMS;
1556 }
1557 if (src_surface)
1558 {
1559 wined3d_mutex_unlock();
1560 WARN("Depth or colorfill is not compatible with source surfaces, returning DDERR_INVALIDPARAMS\n");
1561 return DDERR_INVALIDPARAMS;
1562 }
1563 if (!DDBltFx)
1564 {
1565 wined3d_mutex_unlock();
1566 WARN("Depth or colorfill used with DDBltFx = NULL, returning DDERR_INVALIDPARAMS.\n");
1567 return DDERR_INVALIDPARAMS;
1568 }
1569
1570 if ((Flags & (DDBLT_COLORFILL | DDBLT_DEPTHFILL)) == (DDBLT_COLORFILL | DDBLT_DEPTHFILL))
1571 Flags &= ~DDBLT_DEPTHFILL;
1572
1573 if ((dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (Flags & DDBLT_COLORFILL))
1574 {
1575 wined3d_mutex_unlock();
1576 WARN("DDBLT_COLORFILL used on a depth buffer, returning DDERR_INVALIDPARAMS.\n");
1577 return DDERR_INVALIDPARAMS;
1578 }
1579 if (!(dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (Flags & DDBLT_DEPTHFILL))
1580 {
1581 wined3d_mutex_unlock();
1582 WARN("DDBLT_DEPTHFILL used on a color buffer, returning DDERR_INVALIDPARAMS.\n");
1583 return DDERR_INVALIDPARAMS;
1584 }
1585 }
1586
1587 if (Flags & DDBLT_ROP)
1588 {
1589 if (!DDBltFx)
1590 {
1591 wined3d_mutex_unlock();
1592 WARN("DDBLT_ROP used with DDBltFx = NULL, returning DDERR_INVALIDPARAMS.\n");
1593 return DDERR_INVALIDPARAMS;
1594 }
1595
1596 Flags &= ~DDBLT_ROP;
1597 switch (DDBltFx->dwROP)
1598 {
1599 case SRCCOPY:
1600 break;
1601
1602 case WHITENESS:
1603 case BLACKNESS:
1604 rop_fx = *DDBltFx;
1605
1606 if (DDBltFx->dwROP == WHITENESS)
1607 rop_fx.u5.dwFillColor = 0xffffffff;
1608 else
1609 rop_fx.u5.dwFillColor = 0;
1610
1611 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1612 Flags |= DDBLT_DEPTHFILL;
1613 else
1614 Flags |= DDBLT_COLORFILL;
1615
1616 DDBltFx = &rop_fx;
1617 break;
1618
1619 default:
1620 wined3d_mutex_unlock();
1621 WARN("Unsupported ROP %#x used, returning DDERR_NORASTEROPHW.\n", DDBltFx->dwROP);
1622 return DDERR_NORASTEROPHW;
1623 }
1624 }
1625
1626 if (Flags & DDBLT_KEYSRC && (!src_surface || !(src_surface->surface_desc.dwFlags & DDSD_CKSRCBLT)))
1627 {
1628 WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1629 wined3d_mutex_unlock();
1630 return DDERR_INVALIDPARAMS;
1631 }
1632
1633 /* TODO: Check if the DDBltFx contains any ddraw surface pointers. If it
1634 * does, copy the struct, and replace the ddraw surfaces with the wined3d
1635 * surfaces. So far no blitting operations using surfaces in the bltfx
1636 * struct are supported anyway. */
1637 hr = ddraw_surface_blt_clipped(dst_surface, DestRect, src_surface, SrcRect,
1638 Flags, (WINEDDBLTFX *)DDBltFx, WINED3D_TEXF_LINEAR);
1639
1640 wined3d_mutex_unlock();
1641 switch(hr)
1642 {
1643 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
1644 case WINED3DERR_WRONGTEXTUREFORMAT: return DDERR_INVALIDPIXELFORMAT;
1645 default: return hr;
1646 }
1647 }
1648
1649 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_Blt(IDirectDrawSurface4 *iface, RECT *dst_rect,
1650 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1651 {
1652 struct ddraw_surface *dst = impl_from_IDirectDrawSurface4(iface);
1653 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface4(src_surface);
1654
1655 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1656 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1657
1658 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1659 src ? &src->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1660 }
1661
1662 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_Blt(IDirectDrawSurface3 *iface, RECT *dst_rect,
1663 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1664 {
1665 struct ddraw_surface *dst = impl_from_IDirectDrawSurface3(iface);
1666 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
1667
1668 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1669 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1670
1671 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1672 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1673 }
1674
1675 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_Blt(IDirectDrawSurface2 *iface, RECT *dst_rect,
1676 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1677 {
1678 struct ddraw_surface *dst = impl_from_IDirectDrawSurface2(iface);
1679 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
1680
1681 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1682 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1683
1684 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1685 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1686 }
1687
1688 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Blt(IDirectDrawSurface *iface, RECT *dst_rect,
1689 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1690 {
1691 struct ddraw_surface *dst = impl_from_IDirectDrawSurface(iface);
1692 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
1693
1694 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1695 iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1696
1697 return ddraw_surface7_Blt(&dst->IDirectDrawSurface7_iface, dst_rect,
1698 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1699 }
1700
1701 /*****************************************************************************
1702 * IDirectDrawSurface7::AddAttachedSurface
1703 *
1704 * Attaches a surface to another surface. How the surface attachments work
1705 * is not totally understood yet, and this method is prone to problems.
1706 * The surface that is attached is AddRef-ed.
1707 *
1708 * Tests with complex surfaces suggest that the surface attachments form a
1709 * tree, but no method to test this has been found yet.
1710 *
1711 * The attachment list consists of a first surface (first_attached) and
1712 * for each surface a pointer to the next attached surface (next_attached).
1713 * For the first surface, and a surface that has no attachments
1714 * first_attached points to the surface itself. A surface that has
1715 * no successors in the chain has next_attached set to NULL.
1716 *
1717 * Newly attached surfaces are attached right after the root surface.
1718 * If a surface is attached to a complex surface compound, it's attached to
1719 * the surface that the app requested, not the complex root. See
1720 * GetAttachedSurface for a description how surfaces are found.
1721 *
1722 * This is how the current implementation works, and it was coded by looking
1723 * at the needs of the applications.
1724 *
1725 * So far only Z-Buffer attachments are tested, and they are activated in
1726 * WineD3D. Mipmaps could be tricky to activate in WineD3D.
1727 * Back buffers should work in 2D mode, but they are not tested(They can be
1728 * attached in older iface versions). Rendering to the front buffer and
1729 * switching between that and double buffering is not yet implemented in
1730 * WineD3D, so for 3D it might have unexpected results.
1731 *
1732 * ddraw_surface_attach_surface is the real thing,
1733 * ddraw_surface7_AddAttachedSurface is a wrapper around it that
1734 * performs additional checks. Version 7 of this interface is much more restrictive
1735 * than its predecessors.
1736 *
1737 * Params:
1738 * Attach: Surface to attach to iface
1739 *
1740 * Returns:
1741 * DD_OK on success
1742 * DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
1743 *
1744 *****************************************************************************/
1745 static HRESULT ddraw_surface_attach_surface(struct ddraw_surface *This, struct ddraw_surface *Surf)
1746 {
1747 TRACE("surface %p, attachment %p.\n", This, Surf);
1748
1749 if(Surf == This)
1750 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
1751
1752 wined3d_mutex_lock();
1753
1754 /* Check if the surface is already attached somewhere */
1755 if (Surf->next_attached || Surf->first_attached != Surf)
1756 {
1757 /* TODO: Test for the structure of the manual attachment. Is it a
1758 * chain or a list? What happens if one surface is attached to 2
1759 * different surfaces? */
1760 WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n",
1761 Surf, Surf->next_attached, Surf->first_attached);
1762
1763 wined3d_mutex_unlock();
1764 return DDERR_SURFACEALREADYATTACHED;
1765 }
1766
1767 /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
1768 Surf->next_attached = This->next_attached;
1769 Surf->first_attached = This->first_attached;
1770 This->next_attached = Surf;
1771
1772 /* Check if the WineD3D depth stencil needs updating */
1773 if (This->ddraw->d3ddevice)
1774 d3d_device_update_depth_stencil(This->ddraw->d3ddevice);
1775
1776 wined3d_mutex_unlock();
1777
1778 return DD_OK;
1779 }
1780
1781 static HRESULT WINAPI ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *attachment)
1782 {
1783 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
1784 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
1785 HRESULT hr;
1786
1787 TRACE("iface %p, attachment %p.\n", iface, attachment);
1788
1789 /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
1790 if(!(attachment_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
1791 {
1792
1793 WARN("Application tries to attach a non Z buffer surface. caps %08x\n",
1794 attachment_impl->surface_desc.ddsCaps.dwCaps);
1795 return DDERR_CANNOTATTACHSURFACE;
1796 }
1797
1798 hr = ddraw_surface_attach_surface(This, attachment_impl);
1799 if (FAILED(hr))
1800 {
1801 return hr;
1802 }
1803 attachment_impl->attached_iface = (IUnknown *)attachment;
1804 IUnknown_AddRef(attachment_impl->attached_iface);
1805 return hr;
1806 }
1807
1808 static HRESULT WINAPI ddraw_surface4_AddAttachedSurface(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *attachment)
1809 {
1810 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1811 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
1812 HRESULT hr;
1813
1814 TRACE("iface %p, attachment %p.\n", iface, attachment);
1815
1816 /* Tests suggest that
1817 * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
1818 * -> offscreen plain surfaces can be attached to primaries
1819 * -> primaries can be attached to offscreen plain surfaces
1820 * -> z buffers can be attached to primaries */
1821 if (surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN)
1822 && attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN))
1823 {
1824 /* Sizes have to match */
1825 if (attachment_impl->surface_desc.dwWidth != surface->surface_desc.dwWidth
1826 || attachment_impl->surface_desc.dwHeight != surface->surface_desc.dwHeight)
1827 {
1828 WARN("Surface sizes do not match.\n");
1829 return DDERR_CANNOTATTACHSURFACE;
1830 }
1831 }
1832 else if (!(surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE))
1833 || !(attachment_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)))
1834 {
1835 WARN("Invalid attachment combination.\n");
1836 return DDERR_CANNOTATTACHSURFACE;
1837 }
1838
1839 if (FAILED(hr = ddraw_surface_attach_surface(surface, attachment_impl)))
1840 return hr;
1841
1842 attachment_impl->attached_iface = (IUnknown *)attachment;
1843 IUnknown_AddRef(attachment_impl->attached_iface);
1844 return hr;
1845 }
1846
1847 static HRESULT WINAPI ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *attachment)
1848 {
1849 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
1850 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
1851 HRESULT hr;
1852
1853 TRACE("iface %p, attachment %p.\n", iface, attachment);
1854
1855 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
1856 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
1857 return hr;
1858
1859 attachment_impl->attached_iface = (IUnknown *)attachment;
1860 IUnknown_AddRef(attachment_impl->attached_iface);
1861 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
1862 return hr;
1863 }
1864
1865 static HRESULT WINAPI ddraw_surface2_AddAttachedSurface(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *attachment)
1866 {
1867 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
1868 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
1869 HRESULT hr;
1870
1871 TRACE("iface %p, attachment %p.\n", iface, attachment);
1872
1873 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
1874 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
1875 return hr;
1876
1877 attachment_impl->attached_iface = (IUnknown *)attachment;
1878 IUnknown_AddRef(attachment_impl->attached_iface);
1879 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
1880 return hr;
1881 }
1882
1883 static HRESULT WINAPI ddraw_surface1_AddAttachedSurface(IDirectDrawSurface *iface, IDirectDrawSurface *attachment)
1884 {
1885 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
1886 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
1887 HRESULT hr;
1888
1889 TRACE("iface %p, attachment %p.\n", iface, attachment);
1890
1891 if (FAILED(hr = ddraw_surface4_AddAttachedSurface(&surface->IDirectDrawSurface4_iface,
1892 attachment_impl ? &attachment_impl->IDirectDrawSurface4_iface : NULL)))
1893 return hr;
1894
1895 attachment_impl->attached_iface = (IUnknown *)attachment;
1896 IUnknown_AddRef(attachment_impl->attached_iface);
1897 ddraw_surface4_Release(&attachment_impl->IDirectDrawSurface4_iface);
1898 return hr;
1899 }
1900
1901 /*****************************************************************************
1902 * IDirectDrawSurface7::DeleteAttachedSurface
1903 *
1904 * Removes a surface from the attachment chain. The surface's refcount
1905 * is decreased by one after it has been removed
1906 *
1907 * Params:
1908 * Flags: Some flags, not used by this implementation
1909 * Attach: Surface to detach
1910 *
1911 * Returns:
1912 * DD_OK on success
1913 * DDERR_SURFACENOTATTACHED if the surface isn't attached to
1914 *
1915 *****************************************************************************/
1916 static HRESULT ddraw_surface_delete_attached_surface(struct ddraw_surface *surface,
1917 struct ddraw_surface *attachment, IUnknown *detach_iface)
1918 {
1919 struct ddraw_surface *prev = surface;
1920
1921 TRACE("surface %p, attachment %p, detach_iface %p.\n", surface, attachment, detach_iface);
1922
1923 wined3d_mutex_lock();
1924 if (!attachment || (attachment->first_attached != surface) || (attachment == surface) )
1925 {
1926 wined3d_mutex_unlock();
1927 return DDERR_CANNOTDETACHSURFACE;
1928 }
1929
1930 if (attachment->attached_iface != detach_iface)
1931 {
1932 WARN("attachment->attach_iface %p != detach_iface %p.\n", attachment->attached_iface, detach_iface);
1933 wined3d_mutex_unlock();
1934 return DDERR_SURFACENOTATTACHED;
1935 }
1936
1937 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
1938 if (surface->surface_desc.ddsCaps.dwCaps & attachment->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
1939 {
1940 attachment->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
1941 /* FIXME: we should probably also subtract from dwMipMapCount of this
1942 * and all parent surfaces */
1943 }
1944
1945 /* Find the predecessor of the detached surface */
1946 while (prev)
1947 {
1948 if (prev->next_attached == attachment)
1949 break;
1950 prev = prev->next_attached;
1951 }
1952
1953 /* There must be a surface, otherwise there's a bug */
1954 assert(prev);
1955
1956 /* Unchain the surface */
1957 prev->next_attached = attachment->next_attached;
1958 attachment->next_attached = NULL;
1959 attachment->first_attached = attachment;
1960
1961 /* Check if the wined3d depth stencil needs updating. */
1962 if (surface->ddraw->d3ddevice)
1963 d3d_device_update_depth_stencil(surface->ddraw->d3ddevice);
1964 wined3d_mutex_unlock();
1965
1966 /* Set attached_iface to NULL before releasing it, the surface may go
1967 * away. */
1968 attachment->attached_iface = NULL;
1969 IUnknown_Release(detach_iface);
1970
1971 return DD_OK;
1972 }
1973
1974 static HRESULT WINAPI ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7 *iface,
1975 DWORD flags, IDirectDrawSurface7 *attachment)
1976 {
1977 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
1978 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
1979
1980 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1981
1982 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
1983 }
1984
1985 static HRESULT WINAPI ddraw_surface4_DeleteAttachedSurface(IDirectDrawSurface4 *iface,
1986 DWORD flags, IDirectDrawSurface4 *attachment)
1987 {
1988 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
1989 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
1990
1991 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1992
1993 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
1994 }
1995
1996 static HRESULT WINAPI ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
1997 DWORD flags, IDirectDrawSurface3 *attachment)
1998 {
1999 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2000 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
2001
2002 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2003
2004 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2005 }
2006
2007 static HRESULT WINAPI ddraw_surface2_DeleteAttachedSurface(IDirectDrawSurface2 *iface,
2008 DWORD flags, IDirectDrawSurface2 *attachment)
2009 {
2010 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2011 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
2012
2013 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2014
2015 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2016 }
2017
2018 static HRESULT WINAPI ddraw_surface1_DeleteAttachedSurface(IDirectDrawSurface *iface,
2019 DWORD flags, IDirectDrawSurface *attachment)
2020 {
2021 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2022 struct ddraw_surface *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
2023
2024 TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
2025
2026 return ddraw_surface_delete_attached_surface(surface, attachment_impl, (IUnknown *)attachment);
2027 }
2028
2029 /*****************************************************************************
2030 * IDirectDrawSurface7::AddOverlayDirtyRect
2031 *
2032 * "This method is not currently implemented"
2033 *
2034 * Params:
2035 * Rect: ?
2036 *
2037 * Returns:
2038 * DDERR_UNSUPPORTED
2039 *
2040 *****************************************************************************/
2041 static HRESULT WINAPI ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7 *iface, RECT *Rect)
2042 {
2043 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(Rect));
2044
2045 return DDERR_UNSUPPORTED; /* unchecked */
2046 }
2047
2048 static HRESULT WINAPI ddraw_surface4_AddOverlayDirtyRect(IDirectDrawSurface4 *iface, RECT *rect)
2049 {
2050 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2051
2052 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2053
2054 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2055 }
2056
2057 static HRESULT WINAPI ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3 *iface, RECT *rect)
2058 {
2059 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2060
2061 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2062
2063 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2064 }
2065
2066 static HRESULT WINAPI ddraw_surface2_AddOverlayDirtyRect(IDirectDrawSurface2 *iface, RECT *rect)
2067 {
2068 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2069
2070 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2071
2072 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2073 }
2074
2075 static HRESULT WINAPI ddraw_surface1_AddOverlayDirtyRect(IDirectDrawSurface *iface, RECT *rect)
2076 {
2077 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2078
2079 TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
2080
2081 return ddraw_surface7_AddOverlayDirtyRect(&surface->IDirectDrawSurface7_iface, rect);
2082 }
2083
2084 /*****************************************************************************
2085 * IDirectDrawSurface7::GetDC
2086 *
2087 * Returns a GDI device context for the surface
2088 *
2089 * Params:
2090 * hdc: Address of a HDC variable to store the dc to
2091 *
2092 * Returns:
2093 * DD_OK on success
2094 * DDERR_INVALIDPARAMS if hdc is NULL
2095 * For details, see IWineD3DSurface::GetDC
2096 *
2097 *****************************************************************************/
2098 static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *hdc)
2099 {
2100 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2101 HRESULT hr = DD_OK;
2102
2103 TRACE("iface %p, dc %p.\n", iface, hdc);
2104
2105 if(!hdc)
2106 return DDERR_INVALIDPARAMS;
2107
2108 wined3d_mutex_lock();
2109 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
2110 hr = ddraw_surface_update_frontbuffer(surface, NULL, TRUE);
2111 if (SUCCEEDED(hr))
2112 hr = wined3d_surface_getdc(surface->wined3d_surface, hdc);
2113
2114 if (SUCCEEDED(hr) && format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat))
2115 {
2116 const struct ddraw_palette *palette;
2117
2118 if (surface->palette)
2119 palette = surface->palette;
2120 else if (surface->ddraw->primary)
2121 palette = surface->ddraw->primary->palette;
2122 else
2123 palette = NULL;
2124
2125 if (palette)
2126 wined3d_palette_apply_to_dc(palette->wineD3DPalette, *hdc);
2127 }
2128
2129 wined3d_mutex_unlock();
2130 switch(hr)
2131 {
2132 /* Some, but not all errors set *hdc to NULL. E.g. DCALREADYCREATED does not
2133 * touch *hdc
2134 */
2135 case WINED3DERR_INVALIDCALL:
2136 if(hdc) *hdc = NULL;
2137 return DDERR_INVALIDPARAMS;
2138
2139 default: return hr;
2140 }
2141 }
2142
2143 static HRESULT WINAPI ddraw_surface4_GetDC(IDirectDrawSurface4 *iface, HDC *dc)
2144 {
2145 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2146
2147 TRACE("iface %p, dc %p.\n", iface, dc);
2148
2149 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2150 }
2151
2152 static HRESULT WINAPI ddraw_surface3_GetDC(IDirectDrawSurface3 *iface, HDC *dc)
2153 {
2154 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2155
2156 TRACE("iface %p, dc %p.\n", iface, dc);
2157
2158 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2159 }
2160
2161 static HRESULT WINAPI ddraw_surface2_GetDC(IDirectDrawSurface2 *iface, HDC *dc)
2162 {
2163 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2164
2165 TRACE("iface %p, dc %p.\n", iface, dc);
2166
2167 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2168 }
2169
2170 static HRESULT WINAPI ddraw_surface1_GetDC(IDirectDrawSurface *iface, HDC *dc)
2171 {
2172 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2173
2174 TRACE("iface %p, dc %p.\n", iface, dc);
2175
2176 return ddraw_surface7_GetDC(&surface->IDirectDrawSurface7_iface, dc);
2177 }
2178
2179 /*****************************************************************************
2180 * IDirectDrawSurface7::ReleaseDC
2181 *
2182 * Releases the DC that was constructed with GetDC
2183 *
2184 * Params:
2185 * hdc: HDC to release
2186 *
2187 * Returns:
2188 * DD_OK on success
2189 * For more details, see IWineD3DSurface::ReleaseDC
2190 *
2191 *****************************************************************************/
2192 static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC hdc)
2193 {
2194 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2195 HRESULT hr;
2196
2197 TRACE("iface %p, dc %p.\n", iface, hdc);
2198
2199 wined3d_mutex_lock();
2200 hr = wined3d_surface_releasedc(surface->wined3d_surface, hdc);
2201 if (SUCCEEDED(hr) && (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
2202 hr = ddraw_surface_update_frontbuffer(surface, NULL, FALSE);
2203 wined3d_mutex_unlock();
2204
2205 return hr;
2206 }
2207
2208 static HRESULT WINAPI ddraw_surface4_ReleaseDC(IDirectDrawSurface4 *iface, HDC dc)
2209 {
2210 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2211
2212 TRACE("iface %p, dc %p.\n", iface, dc);
2213
2214 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2215 }
2216
2217 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc)
2218 {
2219 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2220
2221 TRACE("iface %p, dc %p.\n", iface, dc);
2222
2223 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2224 }
2225
2226 static HRESULT WINAPI ddraw_surface2_ReleaseDC(IDirectDrawSurface2 *iface, HDC dc)
2227 {
2228 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2229
2230 TRACE("iface %p, dc %p.\n", iface, dc);
2231
2232 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2233 }
2234
2235 static HRESULT WINAPI ddraw_surface1_ReleaseDC(IDirectDrawSurface *iface, HDC dc)
2236 {
2237 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2238
2239 TRACE("iface %p, dc %p.\n", iface, dc);
2240
2241 return ddraw_surface7_ReleaseDC(&surface->IDirectDrawSurface7_iface, dc);
2242 }
2243
2244 /*****************************************************************************
2245 * IDirectDrawSurface7::GetCaps
2246 *
2247 * Returns the surface's caps
2248 *
2249 * Params:
2250 * Caps: Address to write the caps to
2251 *
2252 * Returns:
2253 * DD_OK on success
2254 * DDERR_INVALIDPARAMS if Caps is NULL
2255 *
2256 *****************************************************************************/
2257 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps)
2258 {
2259 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2260
2261 TRACE("iface %p, caps %p.\n", iface, Caps);
2262
2263 if(!Caps)
2264 return DDERR_INVALIDPARAMS;
2265
2266 *Caps = surface->surface_desc.ddsCaps;
2267
2268 return DD_OK;
2269 }
2270
2271 static HRESULT WINAPI ddraw_surface4_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *caps)
2272 {
2273 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2274
2275 TRACE("iface %p, caps %p.\n", iface, caps);
2276
2277 return ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, caps);
2278 }
2279
2280 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps)
2281 {
2282 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2283 DDSCAPS2 caps2;
2284 HRESULT hr;
2285
2286 TRACE("iface %p, caps %p.\n", iface, caps);
2287
2288 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2289 if (FAILED(hr)) return hr;
2290
2291 caps->dwCaps = caps2.dwCaps;
2292 return hr;
2293 }
2294
2295 static HRESULT WINAPI ddraw_surface2_GetCaps(IDirectDrawSurface2 *iface, DDSCAPS *caps)
2296 {
2297 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2298 DDSCAPS2 caps2;
2299 HRESULT hr;
2300
2301 TRACE("iface %p, caps %p.\n", iface, caps);
2302
2303 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2304 if (FAILED(hr)) return hr;
2305
2306 caps->dwCaps = caps2.dwCaps;
2307 return hr;
2308 }
2309
2310 static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS *caps)
2311 {
2312 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2313 DDSCAPS2 caps2;
2314 HRESULT hr;
2315
2316 TRACE("iface %p, caps %p.\n", iface, caps);
2317
2318 hr = ddraw_surface7_GetCaps(&surface->IDirectDrawSurface7_iface, &caps2);
2319 if (FAILED(hr)) return hr;
2320
2321 caps->dwCaps = caps2.dwCaps;
2322 return hr;
2323 }
2324
2325 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD priority)
2326 {
2327 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2328 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
2329 HRESULT hr;
2330 struct wined3d_resource *resource;
2331
2332 TRACE("iface %p, priority %u.\n", iface, priority);
2333
2334 wined3d_mutex_lock();
2335 /* No need to check for offscreen plain surfaces or mipmap sublevels. SetPriority
2336 * calls on such surfaces segfault on Windows. */
2337 if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed))
2338 {
2339 WARN("Called on non-managed texture returning DDERR_INVALIDPARAMS.\n");
2340 hr = DDERR_INVALIDPARAMS;
2341 }
2342 else
2343 {
2344 resource = wined3d_texture_get_resource(surface->wined3d_texture);
2345 wined3d_resource_set_priority(resource, priority);
2346 hr = DD_OK;
2347 }
2348 wined3d_mutex_unlock();
2349
2350 return hr;
2351 }
2352
2353 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *priority)
2354 {
2355 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2356 const struct wined3d_resource *resource;
2357 DWORD managed = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE;
2358 HRESULT hr;
2359
2360 TRACE("iface %p, priority %p.\n", iface, priority);
2361
2362 wined3d_mutex_lock();
2363 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
2364 {
2365 WARN("Called on offscreenplain surface, returning DDERR_INVALIDOBJECT.\n");
2366 hr = DDERR_INVALIDOBJECT;
2367 }
2368 else if (!(surface->surface_desc.ddsCaps.dwCaps2 & managed) || !surface->wined3d_texture)
2369 {
2370 WARN("Called on non-managed texture or mipmap sublevel, returning DDERR_INVALIDPARAMS.\n");
2371 hr = DDERR_INVALIDPARAMS;
2372 }
2373 else
2374 {
2375 resource = wined3d_texture_get_resource(surface->wined3d_texture);
2376 *priority = wined3d_resource_get_priority(resource);
2377 hr = DD_OK;
2378 }
2379 wined3d_mutex_unlock();
2380
2381 return hr;
2382 }
2383
2384 /*****************************************************************************
2385 * IDirectDrawSurface7::SetPrivateData
2386 *
2387 * Stores some data in the surface that is intended for the application's
2388 * use.
2389 *
2390 * Params:
2391 * tag: GUID that identifies the data
2392 * Data: Pointer to the private data
2393 * Size: Size of the private data
2394 * Flags: Some flags
2395 *
2396 * Returns:
2397 * D3D_OK on success
2398 * For more details, see IWineD3DSurface::SetPrivateData
2399 *
2400 *****************************************************************************/
2401 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface,
2402 REFGUID tag, void *data, DWORD size, DWORD flags)
2403 {
2404 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2405 HRESULT hr;
2406
2407 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2408 iface, debugstr_guid(tag), data, size, flags);
2409
2410 if (!data)
2411 {
2412 WARN("data is NULL, returning DDERR_INVALIDPARAMS.\n");
2413 return DDERR_INVALIDPARAMS;
2414 }
2415
2416 wined3d_mutex_lock();
2417 hr = wined3d_private_store_set_private_data(&surface->private_store, tag, data, size, flags);
2418 wined3d_mutex_unlock();
2419 return hr_ddraw_from_wined3d(hr);
2420 }
2421
2422 static HRESULT WINAPI ddraw_surface4_SetPrivateData(IDirectDrawSurface4 *iface,
2423 REFGUID tag, void *data, DWORD size, DWORD flags)
2424 {
2425 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2426
2427 TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2428 iface, debugstr_guid(tag), data, size, flags);
2429
2430 return ddraw_surface7_SetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size, flags);
2431 }
2432
2433 /*****************************************************************************
2434 * IDirectDrawSurface7::GetPrivateData
2435 *
2436 * Returns the private data set with IDirectDrawSurface7::SetPrivateData
2437 *
2438 * Params:
2439 * tag: GUID of the data to return
2440 * Data: Address where to write the data to
2441 * Size: Size of the buffer at Data
2442 *
2443 * Returns:
2444 * DD_OK on success
2445 * DDERR_INVALIDPARAMS if Data is NULL
2446 * For more details, see IWineD3DSurface::GetPrivateData
2447 *
2448 *****************************************************************************/
2449 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *data, DWORD *size)
2450 {
2451 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2452 const struct wined3d_private_data *stored_data;
2453 HRESULT hr;
2454
2455 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2456 iface, debugstr_guid(tag), data, size);
2457
2458 wined3d_mutex_lock();
2459 stored_data = wined3d_private_store_get_private_data(&surface->private_store, tag);
2460 if (!stored_data)
2461 {
2462 hr = DDERR_NOTFOUND;
2463 goto done;
2464 }
2465 if (!size)
2466 {
2467 hr = DDERR_INVALIDPARAMS;
2468 goto done;
2469 }
2470 if (*size < stored_data->size)
2471 {
2472 *size = stored_data->size;
2473 hr = DDERR_MOREDATA;
2474 goto done;
2475 }
2476 if (!data)
2477 {
2478 hr = DDERR_INVALIDPARAMS;
2479 goto done;
2480 }
2481
2482 *size = stored_data->size;
2483 memcpy(data, stored_data->content.data, stored_data->size);
2484 hr = DD_OK;
2485
2486 done:
2487 wined3d_mutex_unlock();
2488 return hr;
2489 }
2490
2491 static HRESULT WINAPI ddraw_surface4_GetPrivateData(IDirectDrawSurface4 *iface, REFGUID tag, void *data, DWORD *size)
2492 {
2493 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2494
2495 TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2496 iface, debugstr_guid(tag), data, size);
2497
2498 return ddraw_surface7_GetPrivateData(&surface->IDirectDrawSurface7_iface, tag, data, size);
2499 }
2500
2501 /*****************************************************************************
2502 * IDirectDrawSurface7::FreePrivateData
2503 *
2504 * Frees private data stored in the surface
2505 *
2506 * Params:
2507 * tag: Tag of the data to free
2508 *
2509 * Returns:
2510 * D3D_OK on success
2511 * For more details, see IWineD3DSurface::FreePrivateData
2512 *
2513 *****************************************************************************/
2514 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag)
2515 {
2516 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2517 struct wined3d_private_data *entry;
2518
2519 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2520
2521 wined3d_mutex_lock();
2522 entry = wined3d_private_store_get_private_data(&surface->private_store, tag);
2523 if (!entry)
2524 {
2525 wined3d_mutex_unlock();
2526 return DDERR_NOTFOUND;
2527 }
2528
2529 wined3d_private_store_free_private_data(&surface->private_store, entry);
2530 wined3d_mutex_unlock();
2531
2532 return DD_OK;
2533 }
2534
2535 static HRESULT WINAPI ddraw_surface4_FreePrivateData(IDirectDrawSurface4 *iface, REFGUID tag)
2536 {
2537 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2538
2539 TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2540
2541 return ddraw_surface7_FreePrivateData(&surface->IDirectDrawSurface7_iface, tag);
2542 }
2543
2544 /*****************************************************************************
2545 * IDirectDrawSurface7::PageLock
2546 *
2547 * Prevents a sysmem surface from being paged out
2548 *
2549 * Params:
2550 * Flags: Not used, must be 0(unchecked)
2551 *
2552 * Returns:
2553 * DD_OK, because it's a stub
2554 *
2555 *****************************************************************************/
2556 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags)
2557 {
2558 TRACE("iface %p, flags %#x.\n", iface, Flags);
2559
2560 /* This is Windows memory management related - we don't need this */
2561 return DD_OK;
2562 }
2563
2564 static HRESULT WINAPI ddraw_surface4_PageLock(IDirectDrawSurface4 *iface, DWORD flags)
2565 {
2566 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2567
2568 TRACE("iface %p, flags %#x.\n", iface, flags);
2569
2570 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2571 }
2572
2573 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags)
2574 {
2575 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2576
2577 TRACE("iface %p, flags %#x.\n", iface, flags);
2578
2579 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2580 }
2581
2582 static HRESULT WINAPI ddraw_surface2_PageLock(IDirectDrawSurface2 *iface, DWORD flags)
2583 {
2584 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2585
2586 TRACE("iface %p, flags %#x.\n", iface, flags);
2587
2588 return ddraw_surface7_PageLock(&surface->IDirectDrawSurface7_iface, flags);
2589 }
2590
2591 /*****************************************************************************
2592 * IDirectDrawSurface7::PageUnlock
2593 *
2594 * Allows a sysmem surface to be paged out
2595 *
2596 * Params:
2597 * Flags: Not used, must be 0(unchecked)
2598 *
2599 * Returns:
2600 * DD_OK, because it's a stub
2601 *
2602 *****************************************************************************/
2603 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags)
2604 {
2605 TRACE("iface %p, flags %#x.\n", iface, Flags);
2606
2607 return DD_OK;
2608 }
2609
2610 static HRESULT WINAPI ddraw_surface4_PageUnlock(IDirectDrawSurface4 *iface, DWORD flags)
2611 {
2612 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2613
2614 TRACE("iface %p, flags %#x.\n", iface, flags);
2615
2616 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2617 }
2618
2619 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags)
2620 {
2621 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2622
2623 TRACE("iface %p, flags %#x.\n", iface, flags);
2624
2625 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2626 }
2627
2628 static HRESULT WINAPI ddraw_surface2_PageUnlock(IDirectDrawSurface2 *iface, DWORD flags)
2629 {
2630 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2631
2632 TRACE("iface %p, flags %#x.\n", iface, flags);
2633
2634 return ddraw_surface7_PageUnlock(&surface->IDirectDrawSurface7_iface, flags);
2635 }
2636
2637 /*****************************************************************************
2638 * IDirectDrawSurface7::BltBatch
2639 *
2640 * An unimplemented function
2641 *
2642 * Params:
2643 * ?
2644 *
2645 * Returns:
2646 * DDERR_UNSUPPORTED
2647 *
2648 *****************************************************************************/
2649 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
2650 {
2651 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, Batch, Count, Flags);
2652
2653 /* MSDN: "not currently implemented" */
2654 return DDERR_UNSUPPORTED;
2655 }
2656
2657 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltBatch(IDirectDrawSurface4 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2658 {
2659 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2660
2661 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2662
2663 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2664 }
2665
2666 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2667 {
2668 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2669
2670 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2671
2672 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2673 }
2674
2675 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltBatch(IDirectDrawSurface2 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2676 {
2677 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2678
2679 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2680
2681 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2682 }
2683
2684 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltBatch(IDirectDrawSurface *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2685 {
2686 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2687
2688 TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2689
2690 return ddraw_surface7_BltBatch(&surface->IDirectDrawSurface7_iface, batch, count, flags);
2691 }
2692
2693 /*****************************************************************************
2694 * IDirectDrawSurface7::EnumAttachedSurfaces
2695 *
2696 * Enumerates all surfaces attached to this surface
2697 *
2698 * Params:
2699 * context: Pointer to pass unmodified to the callback
2700 * cb: Callback function to call for each surface
2701 *
2702 * Returns:
2703 * DD_OK on success
2704 * DDERR_INVALIDPARAMS if cb is NULL
2705 *
2706 *****************************************************************************/
2707 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface,
2708 void *context, LPDDENUMSURFACESCALLBACK7 cb)
2709 {
2710 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
2711 struct ddraw_surface *surf;
2712 DDSURFACEDESC2 desc;
2713 int i;
2714
2715 /* Attached surfaces aren't handled in WineD3D */
2716 TRACE("iface %p, context %p, callback %p.\n", iface, context, cb);
2717
2718 if(!cb)
2719 return DDERR_INVALIDPARAMS;
2720
2721 wined3d_mutex_lock();
2722
2723 for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
2724 {
2725 surf = surface->complex_array[i];
2726 if(!surf) break;
2727
2728 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2729 desc = surf->surface_desc;
2730 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2731 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2732 {
2733 wined3d_mutex_unlock();
2734 return DD_OK;
2735 }
2736 }
2737
2738 for (surf = surface->next_attached; surf != NULL; surf = surf->next_attached)
2739 {
2740 ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2741 desc = surf->surface_desc;
2742 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2743 if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2744 {
2745 wined3d_mutex_unlock();
2746 return DD_OK;
2747 }
2748 }
2749
2750 TRACE(" end of enumeration.\n");
2751
2752 wined3d_mutex_unlock();
2753
2754 return DD_OK;
2755 }
2756
2757 struct callback_info2
2758 {
2759 LPDDENUMSURFACESCALLBACK2 callback;
2760 void *context;
2761 };
2762
2763 struct callback_info
2764 {
2765 LPDDENUMSURFACESCALLBACK callback;
2766 void *context;
2767 };
2768
2769 static HRESULT CALLBACK EnumCallback2(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2770 {
2771 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
2772 const struct callback_info2 *info = context;
2773
2774 ddraw_surface4_AddRef(&surface_impl->IDirectDrawSurface4_iface);
2775 ddraw_surface7_Release(surface);
2776
2777 return info->callback(&surface_impl->IDirectDrawSurface4_iface, surface_desc, info->context);
2778 }
2779
2780 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2781 {
2782 struct ddraw_surface *surface_impl = impl_from_IDirectDrawSurface7(surface);
2783 const struct callback_info *info = context;
2784
2785 ddraw_surface1_AddRef(&surface_impl->IDirectDrawSurface_iface);
2786 ddraw_surface7_Release(surface);
2787
2788 /* FIXME: Check surface_test.dwSize */
2789 return info->callback(&surface_impl->IDirectDrawSurface_iface,
2790 (DDSURFACEDESC *)surface_desc, info->context);
2791 }
2792
2793 static HRESULT WINAPI ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4 *iface,
2794 void *context, LPDDENUMSURFACESCALLBACK2 callback)
2795 {
2796 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2797 struct callback_info2 info;
2798
2799 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2800
2801 info.callback = callback;
2802 info.context = context;
2803
2804 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2805 &info, EnumCallback2);
2806 }
2807
2808 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
2809 void *context, LPDDENUMSURFACESCALLBACK callback)
2810 {
2811 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2812 struct callback_info info;
2813
2814 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2815
2816 info.callback = callback;
2817 info.context = context;
2818
2819 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2820 &info, EnumCallback);
2821 }
2822
2823 static HRESULT WINAPI ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2 *iface,
2824 void *context, LPDDENUMSURFACESCALLBACK callback)
2825 {
2826 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2827 struct callback_info info;
2828
2829 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2830
2831 info.callback = callback;
2832 info.context = context;
2833
2834 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2835 &info, EnumCallback);
2836 }
2837
2838 static HRESULT WINAPI ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface *iface,
2839 void *context, LPDDENUMSURFACESCALLBACK callback)
2840 {
2841 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2842 struct callback_info info;
2843
2844 TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2845
2846 info.callback = callback;
2847 info.context = context;
2848
2849 return ddraw_surface7_EnumAttachedSurfaces(&surface->IDirectDrawSurface7_iface,
2850 &info, EnumCallback);
2851 }
2852
2853 /*****************************************************************************
2854 * IDirectDrawSurface7::EnumOverlayZOrders
2855 *
2856 * "Enumerates the overlay surfaces on the specified destination"
2857 *
2858 * Params:
2859 * Flags: DDENUMOVERLAYZ_BACKTOFRONT or DDENUMOVERLAYZ_FRONTTOBACK
2860 * context: context to pass back to the callback
2861 * cb: callback function to call for each enumerated surface
2862 *
2863 * Returns:
2864 * DD_OK, because it's a stub
2865 *
2866 *****************************************************************************/
2867 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface,
2868 DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb)
2869 {
2870 FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface, Flags, context, cb);
2871
2872 return DD_OK;
2873 }
2874
2875 static HRESULT WINAPI ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4 *iface,
2876 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK2 callback)
2877 {
2878 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2879 struct callback_info2 info;
2880
2881 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2882
2883 info.callback = callback;
2884 info.context = context;
2885
2886 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
2887 flags, &info, EnumCallback2);
2888 }
2889
2890 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
2891 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
2892 {
2893 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2894 struct callback_info info;
2895
2896 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2897
2898 info.callback = callback;
2899 info.context = context;
2900
2901 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
2902 flags, &info, EnumCallback);
2903 }
2904
2905 static HRESULT WINAPI ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2 *iface,
2906 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
2907 {
2908 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2909 struct callback_info info;
2910
2911 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2912
2913 info.callback = callback;
2914 info.context = context;
2915
2916 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
2917 flags, &info, EnumCallback);
2918 }
2919
2920 static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *iface,
2921 DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
2922 {
2923 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2924 struct callback_info info;
2925
2926 TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2927
2928 info.callback = callback;
2929 info.context = context;
2930
2931 return ddraw_surface7_EnumOverlayZOrders(&surface->IDirectDrawSurface7_iface,
2932 flags, &info, EnumCallback);
2933 }
2934
2935 /*****************************************************************************
2936 * IDirectDrawSurface7::GetBltStatus
2937 *
2938 * Returns the blitting status
2939 *
2940 * Params:
2941 * Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
2942 *
2943 * Returns:
2944 * See IWineD3DSurface::Blt
2945 *
2946 *****************************************************************************/
2947 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags)
2948 {
2949 TRACE("iface %p, flags %#x.\n", iface, Flags);
2950
2951 switch (Flags)
2952 {
2953 case WINEDDGBS_CANBLT:
2954 case WINEDDGBS_ISBLTDONE:
2955 return DD_OK;
2956
2957 default:
2958 return DDERR_INVALIDPARAMS;
2959 }
2960 }
2961
2962 static HRESULT WINAPI ddraw_surface4_GetBltStatus(IDirectDrawSurface4 *iface, DWORD flags)
2963 {
2964 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
2965
2966 TRACE("iface %p, flags %#x.\n", iface, flags);
2967
2968 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
2969 }
2970
2971 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags)
2972 {
2973 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
2974
2975 TRACE("iface %p, flags %#x.\n", iface, flags);
2976
2977 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
2978 }
2979
2980 static HRESULT WINAPI ddraw_surface2_GetBltStatus(IDirectDrawSurface2 *iface, DWORD flags)
2981 {
2982 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
2983
2984 TRACE("iface %p, flags %#x.\n", iface, flags);
2985
2986 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
2987 }
2988
2989 static HRESULT WINAPI ddraw_surface1_GetBltStatus(IDirectDrawSurface *iface, DWORD flags)
2990 {
2991 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
2992
2993 TRACE("iface %p, flags %#x.\n", iface, flags);
2994
2995 return ddraw_surface7_GetBltStatus(&surface->IDirectDrawSurface7_iface, flags);
2996 }
2997
2998 /*****************************************************************************
2999 * IDirectDrawSurface7::GetColorKey
3000 *
3001 * Returns the color key assigned to the surface
3002 *
3003 * Params:
3004 * Flags: Some flags
3005 * CKey: Address to store the key to
3006 *
3007 * Returns:
3008 * DD_OK on success
3009 * DDERR_INVALIDPARAMS if CKey is NULL
3010 *
3011 *****************************************************************************/
3012 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
3013 {
3014 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
3015
3016 TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
3017
3018 if(!CKey)
3019 return DDERR_INVALIDPARAMS;
3020
3021 wined3d_mutex_lock();
3022
3023 switch (Flags)
3024 {
3025 case DDCKEY_DESTBLT:
3026 if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT))
3027 {
3028 wined3d_mutex_unlock();
3029 return DDERR_NOCOLORKEY;
3030 }
3031 *CKey = This->surface_desc.ddckCKDestBlt;
3032 break;
3033
3034 case DDCKEY_DESTOVERLAY:
3035 if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY))
3036 {
3037 wined3d_mutex_unlock();
3038 return DDERR_NOCOLORKEY;
3039 }
3040 *CKey = This->surface_desc.u3.ddckCKDestOverlay;
3041 break;
3042
3043 case DDCKEY_SRCBLT:
3044 if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT))
3045 {
3046 wined3d_mutex_unlock();
3047 return DDERR_NOCOLORKEY;
3048 }
3049 *CKey = This->surface_desc.ddckCKSrcBlt;
3050 break;
3051
3052 case DDCKEY_SRCOVERLAY:
3053 if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY))
3054 {
3055 wined3d_mutex_unlock();
3056 return DDERR_NOCOLORKEY;
3057 }
3058 *CKey = This->surface_desc.ddckCKSrcOverlay;
3059 break;
3060
3061 default:
3062 wined3d_mutex_unlock();
3063 return DDERR_INVALIDPARAMS;
3064 }
3065
3066 wined3d_mutex_unlock();
3067
3068 return DD_OK;
3069 }
3070
3071 static HRESULT WINAPI ddraw_surface4_GetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
3072 {
3073 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3074
3075 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3076
3077 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3078 }
3079
3080 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
3081 {
3082 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3083
3084 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3085
3086 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3087 }
3088
3089 static HRESULT WINAPI ddraw_surface2_GetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
3090 {
3091 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3092
3093 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3094
3095 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3096 }
3097
3098 static HRESULT WINAPI ddraw_surface1_GetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
3099 {
3100 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3101
3102 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
3103
3104 return ddraw_surface7_GetColorKey(&surface->IDirectDrawSurface7_iface, flags, color_key);
3105 }
3106
3107 /*****************************************************************************
3108 * IDirectDrawSurface7::GetFlipStatus
3109 *
3110 * Returns the flipping status of the surface
3111 *
3112 * Params:
3113 * Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
3114 *
3115 * Returns:
3116 * See IWineD3DSurface::GetFlipStatus
3117 *
3118 *****************************************************************************/
3119 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags)
3120 {
3121 TRACE("iface %p, flags %#x.\n", iface, Flags);
3122
3123 /* XXX: DDERR_INVALIDSURFACETYPE */
3124
3125 switch (Flags)
3126 {
3127 case WINEDDGFS_CANFLIP:
3128 case WINEDDGFS_ISFLIPDONE:
3129 return DD_OK;
3130
3131 default:
3132 return DDERR_INVALIDPARAMS;
3133 }
3134 }
3135
3136 static HRESULT WINAPI ddraw_surface4_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD flags)
3137 {
3138 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3139
3140 TRACE("iface %p, flags %#x.\n", iface, flags);
3141
3142 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3143 }
3144
3145 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags)
3146 {
3147 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3148
3149 TRACE("iface %p, flags %#x.\n", iface, flags);
3150
3151 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3152 }
3153
3154 static HRESULT WINAPI ddraw_surface2_GetFlipStatus(IDirectDrawSurface2 *iface, DWORD flags)
3155 {
3156 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3157
3158 TRACE("iface %p, flags %#x.\n", iface, flags);
3159
3160 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3161 }
3162
3163 static HRESULT WINAPI ddraw_surface1_GetFlipStatus(IDirectDrawSurface *iface, DWORD flags)
3164 {
3165 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3166
3167 TRACE("iface %p, flags %#x.\n", iface, flags);
3168
3169 return ddraw_surface7_GetFlipStatus(&surface->IDirectDrawSurface7_iface, flags);
3170 }
3171
3172 /*****************************************************************************
3173 * IDirectDrawSurface7::GetOverlayPosition
3174 *
3175 * Returns the display coordinates of a visible and active overlay surface
3176 *
3177 * Params:
3178 * X
3179 * Y
3180 *
3181 * Returns:
3182 * DDERR_NOTAOVERLAYSURFACE, because it's a stub
3183 *****************************************************************************/
3184 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *X, LONG *Y)
3185 {
3186 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3187 HRESULT hr;
3188
3189 TRACE("iface %p, x %p, y %p.\n", iface, X, Y);
3190
3191 wined3d_mutex_lock();
3192 hr = wined3d_surface_get_overlay_position(surface->wined3d_surface, X, Y);
3193 wined3d_mutex_unlock();
3194
3195 return hr;
3196 }
3197
3198 static HRESULT WINAPI ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4 *iface, LONG *x, LONG *y)
3199 {
3200 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3201
3202 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3203
3204 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3205 }
3206
3207 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y)
3208 {
3209 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3210
3211 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3212
3213 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3214 }
3215
3216 static HRESULT WINAPI ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2 *iface, LONG *x, LONG *y)
3217 {
3218 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3219
3220 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3221
3222 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3223 }
3224
3225 static HRESULT WINAPI ddraw_surface1_GetOverlayPosition(IDirectDrawSurface *iface, LONG *x, LONG *y)
3226 {
3227 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3228
3229 TRACE("iface %p, x %p, y %p.\n", iface, x, y);
3230
3231 return ddraw_surface7_GetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3232 }
3233
3234 /*****************************************************************************
3235 * IDirectDrawSurface7::GetPixelFormat
3236 *
3237 * Returns the pixel format of the Surface
3238 *
3239 * Params:
3240 * PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
3241 * format should be written
3242 *
3243 * Returns:
3244 * DD_OK on success
3245 * DDERR_INVALIDPARAMS if PixelFormat is NULL
3246 *
3247 *****************************************************************************/
3248 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat)
3249 {
3250 /* What is DDERR_INVALIDSURFACETYPE for here? */
3251 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3252
3253 TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat);
3254
3255 if(!PixelFormat)
3256 return DDERR_INVALIDPARAMS;
3257
3258 wined3d_mutex_lock();
3259 DD_STRUCT_COPY_BYSIZE(PixelFormat, &surface->surface_desc.u4.ddpfPixelFormat);
3260 wined3d_mutex_unlock();
3261
3262 return DD_OK;
3263 }
3264
3265 static HRESULT WINAPI ddraw_surface4_GetPixelFormat(IDirectDrawSurface4 *iface, DDPIXELFORMAT *pixel_format)
3266 {
3267 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3268
3269 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3270
3271 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3272 }
3273
3274 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format)
3275 {
3276 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3277
3278 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3279
3280 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3281 }
3282
3283 static HRESULT WINAPI ddraw_surface2_GetPixelFormat(IDirectDrawSurface2 *iface, DDPIXELFORMAT *pixel_format)
3284 {
3285 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3286
3287 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3288
3289 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3290 }
3291
3292 static HRESULT WINAPI ddraw_surface1_GetPixelFormat(IDirectDrawSurface *iface, DDPIXELFORMAT *pixel_format)
3293 {
3294 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3295
3296 TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
3297
3298 return ddraw_surface7_GetPixelFormat(&surface->IDirectDrawSurface7_iface, pixel_format);
3299 }
3300
3301 /*****************************************************************************
3302 * IDirectDrawSurface7::GetSurfaceDesc
3303 *
3304 * Returns the description of this surface
3305 *
3306 * Params:
3307 * DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
3308 * surface desc
3309 *
3310 * Returns:
3311 * DD_OK on success
3312 * DDERR_INVALIDPARAMS if DDSD is NULL
3313 *
3314 *****************************************************************************/
3315 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD)
3316 {
3317 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3318
3319 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3320
3321 if(!DDSD)
3322 return DDERR_INVALIDPARAMS;
3323
3324 if (DDSD->dwSize != sizeof(DDSURFACEDESC2))
3325 {
3326 WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize);
3327 return DDERR_INVALIDPARAMS;
3328 }
3329
3330 wined3d_mutex_lock();
3331 DD_STRUCT_COPY_BYSIZE(DDSD, &surface->surface_desc);
3332 TRACE("Returning surface desc:\n");
3333 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
3334 wined3d_mutex_unlock();
3335
3336 return DD_OK;
3337 }
3338
3339 static HRESULT WINAPI ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4 *iface, DDSURFACEDESC2 *DDSD)
3340 {
3341 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3342
3343 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3344
3345 return ddraw_surface7_GetSurfaceDesc(&surface->IDirectDrawSurface7_iface, DDSD);
3346 }
3347
3348 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc)
3349 {
3350 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3351
3352 TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
3353
3354 if (!surface_desc) return DDERR_INVALIDPARAMS;
3355
3356 if (surface_desc->dwSize != sizeof(DDSURFACEDESC))
3357 {
3358 WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize);
3359 return DDERR_INVALIDPARAMS;
3360 }
3361
3362 wined3d_mutex_lock();
3363 DDSD2_to_DDSD(&surface->surface_desc, surface_desc);
3364 TRACE("Returning surface desc:\n");
3365 if (TRACE_ON(ddraw))
3366 {
3367 /* DDRAW_dump_surface_desc handles the smaller size */
3368 DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
3369 }
3370 wined3d_mutex_unlock();
3371
3372 return DD_OK;
3373 }
3374
3375 static HRESULT WINAPI ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2 *iface, DDSURFACEDESC *DDSD)
3376 {
3377 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3378
3379 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3380
3381 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD);
3382 }
3383
3384 static HRESULT WINAPI ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface *iface, DDSURFACEDESC *DDSD)
3385 {
3386 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3387
3388 TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
3389
3390 return ddraw_surface3_GetSurfaceDesc(&surface->IDirectDrawSurface3_iface, DDSD);
3391 }
3392
3393 /*****************************************************************************
3394 * IDirectDrawSurface7::Initialize
3395 *
3396 * Initializes the surface. This is a no-op in Wine
3397 *
3398 * Params:
3399 * DD: Pointer to an DirectDraw interface
3400 * DDSD: Surface description for initialization
3401 *
3402 * Returns:
3403 * DDERR_ALREADYINITIALIZED
3404 *
3405 *****************************************************************************/
3406 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface,
3407 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3408 {
3409 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3410
3411 return DDERR_ALREADYINITIALIZED;
3412 }
3413
3414 static HRESULT WINAPI ddraw_surface4_Initialize(IDirectDrawSurface4 *iface,
3415 IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
3416 {
3417 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3418
3419 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3420
3421 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3422 ddraw, surface_desc);
3423 }
3424
3425 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface,
3426 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3427 {
3428 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3429 DDSURFACEDESC2 surface_desc2;
3430
3431 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3432
3433 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3434 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3435 ddraw, surface_desc ? &surface_desc2 : NULL);
3436 }
3437
3438 static HRESULT WINAPI ddraw_surface2_Initialize(IDirectDrawSurface2 *iface,
3439 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3440 {
3441 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3442 DDSURFACEDESC2 surface_desc2;
3443
3444 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3445
3446 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3447 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3448 ddraw, surface_desc ? &surface_desc2 : NULL);
3449 }
3450
3451 static HRESULT WINAPI ddraw_surface1_Initialize(IDirectDrawSurface *iface,
3452 IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3453 {
3454 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3455 DDSURFACEDESC2 surface_desc2;
3456
3457 TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3458
3459 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3460 return ddraw_surface7_Initialize(&surface->IDirectDrawSurface7_iface,
3461 ddraw, surface_desc ? &surface_desc2 : NULL);
3462 }
3463
3464 /*****************************************************************************
3465 * IDirect3DTexture1::Initialize
3466 *
3467 * The sdk says it's not implemented
3468 *
3469 * Params:
3470 * ?
3471 *
3472 * Returns
3473 * DDERR_UNSUPPORTED
3474 *
3475 *****************************************************************************/
3476 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface,
3477 IDirect3DDevice *device, IDirectDrawSurface *surface)
3478 {
3479 TRACE("iface %p, device %p, surface %p.\n", iface, device, surface);
3480
3481 return DDERR_UNSUPPORTED; /* Unchecked */
3482 }
3483
3484 /*****************************************************************************
3485 * IDirectDrawSurface7::IsLost
3486 *
3487 * Checks if the surface is lost
3488 *
3489 * Returns:
3490 * DD_OK, if the surface is usable
3491 * DDERR_ISLOST if the surface is lost
3492 * See IWineD3DSurface::IsLost for more details
3493 *
3494 *****************************************************************************/
3495 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface)
3496 {
3497 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3498 HRESULT hr;
3499
3500 TRACE("iface %p.\n", iface);
3501
3502 wined3d_mutex_lock();
3503 hr = wined3d_surface_is_lost(surface->wined3d_surface);
3504 wined3d_mutex_unlock();
3505
3506 switch(hr)
3507 {
3508 /* D3D8 and 9 loose full devices, thus there's only a DEVICELOST error.
3509 * WineD3D uses the same error for surfaces
3510 */
3511 case WINED3DERR_DEVICELOST: return DDERR_SURFACELOST;
3512 default: return hr;
3513 }
3514 }
3515
3516 static HRESULT WINAPI ddraw_surface4_IsLost(IDirectDrawSurface4 *iface)
3517 {
3518 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3519
3520 TRACE("iface %p.\n", iface);
3521
3522 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3523 }
3524
3525 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface)
3526 {
3527 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3528
3529 TRACE("iface %p.\n", iface);
3530
3531 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3532 }
3533
3534 static HRESULT WINAPI ddraw_surface2_IsLost(IDirectDrawSurface2 *iface)
3535 {
3536 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3537
3538 TRACE("iface %p.\n", iface);
3539
3540 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3541 }
3542
3543 static HRESULT WINAPI ddraw_surface1_IsLost(IDirectDrawSurface *iface)
3544 {
3545 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3546
3547 TRACE("iface %p.\n", iface);
3548
3549 return ddraw_surface7_IsLost(&surface->IDirectDrawSurface7_iface);
3550 }
3551
3552 /*****************************************************************************
3553 * IDirectDrawSurface7::Restore
3554 *
3555 * Restores a lost surface. This makes the surface usable again, but
3556 * doesn't reload its old contents
3557 *
3558 * Returns:
3559 * DD_OK on success
3560 * See IWineD3DSurface::Restore for more details
3561 *
3562 *****************************************************************************/
3563 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface)
3564 {
3565 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3566 HRESULT hr;
3567
3568 TRACE("iface %p.\n", iface);
3569
3570 wined3d_mutex_lock();
3571 hr = wined3d_surface_restore(surface->wined3d_surface);
3572 wined3d_mutex_unlock();
3573
3574 return hr;
3575 }
3576
3577 static HRESULT WINAPI ddraw_surface4_Restore(IDirectDrawSurface4 *iface)
3578 {
3579 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3580
3581 TRACE("iface %p.\n", iface);
3582
3583 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3584 }
3585
3586 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface)
3587 {
3588 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3589
3590 TRACE("iface %p.\n", iface);
3591
3592 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3593 }
3594
3595 static HRESULT WINAPI ddraw_surface2_Restore(IDirectDrawSurface2 *iface)
3596 {
3597 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3598
3599 TRACE("iface %p.\n", iface);
3600
3601 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3602 }
3603
3604 static HRESULT WINAPI ddraw_surface1_Restore(IDirectDrawSurface *iface)
3605 {
3606 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3607
3608 TRACE("iface %p.\n", iface);
3609
3610 return ddraw_surface7_Restore(&surface->IDirectDrawSurface7_iface);
3611 }
3612
3613 /*****************************************************************************
3614 * IDirectDrawSurface7::SetOverlayPosition
3615 *
3616 * Changes the display coordinates of an overlay surface
3617 *
3618 * Params:
3619 * X:
3620 * Y:
3621 *
3622 * Returns:
3623 * DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
3624 *****************************************************************************/
3625 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG X, LONG Y)
3626 {
3627 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3628 HRESULT hr;
3629
3630 TRACE("iface %p, x %d, y %d.\n", iface, X, Y);
3631
3632 wined3d_mutex_lock();
3633 hr = wined3d_surface_set_overlay_position(surface->wined3d_surface, X, Y);
3634 wined3d_mutex_unlock();
3635
3636 return hr;
3637 }
3638
3639 static HRESULT WINAPI ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4 *iface, LONG x, LONG y)
3640 {
3641 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3642
3643 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3644
3645 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3646 }
3647
3648 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y)
3649 {
3650 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3651
3652 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3653
3654 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3655 }
3656
3657 static HRESULT WINAPI ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2 *iface, LONG x, LONG y)
3658 {
3659 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3660
3661 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3662
3663 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3664 }
3665
3666 static HRESULT WINAPI ddraw_surface1_SetOverlayPosition(IDirectDrawSurface *iface, LONG x, LONG y)
3667 {
3668 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3669
3670 TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3671
3672 return ddraw_surface7_SetOverlayPosition(&surface->IDirectDrawSurface7_iface, x, y);
3673 }
3674
3675 /*****************************************************************************
3676 * IDirectDrawSurface7::UpdateOverlay
3677 *
3678 * Modifies the attributes of an overlay surface.
3679 *
3680 * Params:
3681 * SrcRect: The section of the source being used for the overlay
3682 * DstSurface: Address of the surface that is overlaid
3683 * DstRect: Place of the overlay
3684 * Flags: some DDOVER_* flags
3685 *
3686 * Returns:
3687 * DDERR_UNSUPPORTED, because we don't support overlays
3688 *
3689 *****************************************************************************/
3690 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *SrcRect,
3691 IDirectDrawSurface7 *DstSurface, RECT *DstRect, DWORD Flags, DDOVERLAYFX *FX)
3692 {
3693 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface7(iface);
3694 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface7(DstSurface);
3695 HRESULT hr;
3696
3697 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3698 iface, wine_dbgstr_rect(SrcRect), DstSurface, wine_dbgstr_rect(DstRect), Flags, FX);
3699
3700 wined3d_mutex_lock();
3701 hr = wined3d_surface_update_overlay(src_impl->wined3d_surface, SrcRect,
3702 dst_impl ? dst_impl->wined3d_surface : NULL, DstRect, Flags, (WINEDDOVERLAYFX *)FX);
3703 wined3d_mutex_unlock();
3704
3705 switch(hr) {
3706 case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS;
3707 case WINEDDERR_NOTAOVERLAYSURFACE: return DDERR_NOTAOVERLAYSURFACE;
3708 case WINEDDERR_OVERLAYNOTVISIBLE: return DDERR_OVERLAYNOTVISIBLE;
3709 default:
3710 return hr;
3711 }
3712 }
3713
3714 static HRESULT WINAPI ddraw_surface4_UpdateOverlay(IDirectDrawSurface4 *iface, RECT *src_rect,
3715 IDirectDrawSurface4 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3716 {
3717 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface4(iface);
3718 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst_surface);
3719
3720 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3721 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3722
3723 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3724 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3725 }
3726
3727 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect,
3728 IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3729 {
3730 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface3(iface);
3731 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface);
3732
3733 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3734 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3735
3736 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3737 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3738 }
3739
3740 static HRESULT WINAPI ddraw_surface2_UpdateOverlay(IDirectDrawSurface2 *iface, RECT *src_rect,
3741 IDirectDrawSurface2 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3742 {
3743 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface2(iface);
3744 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst_surface);
3745
3746 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3747 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3748
3749 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3750 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3751 }
3752
3753 static HRESULT WINAPI ddraw_surface1_UpdateOverlay(IDirectDrawSurface *iface, RECT *src_rect,
3754 IDirectDrawSurface *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3755 {
3756 struct ddraw_surface *src_impl = impl_from_IDirectDrawSurface(iface);
3757 struct ddraw_surface *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst_surface);
3758
3759 TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3760 iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3761
3762 return ddraw_surface7_UpdateOverlay(&src_impl->IDirectDrawSurface7_iface, src_rect,
3763 dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3764 }
3765
3766 /*****************************************************************************
3767 * IDirectDrawSurface7::UpdateOverlayDisplay
3768 *
3769 * The DX7 sdk says that it's not implemented
3770 *
3771 * Params:
3772 * Flags: ?
3773 *
3774 * Returns: DDERR_UNSUPPORTED, because we don't support overlays
3775 *
3776 *****************************************************************************/
3777 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags)
3778 {
3779 TRACE("iface %p, flags %#x.\n", iface, Flags);
3780
3781 return DDERR_UNSUPPORTED;
3782 }
3783
3784 static HRESULT WINAPI ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4 *iface, DWORD flags)
3785 {
3786 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3787
3788 TRACE("iface %p, flags %#x.\n", iface, flags);
3789
3790 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
3791 }
3792
3793 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags)
3794 {
3795 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3796
3797 TRACE("iface %p, flags %#x.\n", iface, flags);
3798
3799 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
3800 }
3801
3802 static HRESULT WINAPI ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2 *iface, DWORD flags)
3803 {
3804 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3805
3806 TRACE("iface %p, flags %#x.\n", iface, flags);
3807
3808 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
3809 }
3810
3811 static HRESULT WINAPI ddraw_surface1_UpdateOverlayDisplay(IDirectDrawSurface *iface, DWORD flags)
3812 {
3813 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3814
3815 TRACE("iface %p, flags %#x.\n", iface, flags);
3816
3817 return ddraw_surface7_UpdateOverlayDisplay(&surface->IDirectDrawSurface7_iface, flags);
3818 }
3819
3820 /*****************************************************************************
3821 * IDirectDrawSurface7::UpdateOverlayZOrder
3822 *
3823 * Sets an overlay's Z order
3824 *
3825 * Params:
3826 * Flags: DDOVERZ_* flags
3827 * DDSRef: Defines the relative position in the overlay chain
3828 *
3829 * Returns:
3830 * DDERR_NOTOVERLAYSURFACE, because we don't support overlays
3831 *
3832 *****************************************************************************/
3833 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface,
3834 DWORD Flags, IDirectDrawSurface7 *DDSRef)
3835 {
3836 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
3837 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface7(DDSRef);
3838 HRESULT hr;
3839
3840 TRACE("iface %p, flags %#x, reference %p.\n", iface, Flags, DDSRef);
3841
3842 wined3d_mutex_lock();
3843 hr = wined3d_surface_update_overlay_z_order(surface->wined3d_surface,
3844 Flags, reference_impl ? reference_impl->wined3d_surface : NULL);
3845 wined3d_mutex_unlock();
3846
3847 return hr;
3848 }
3849
3850 static HRESULT WINAPI ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4 *iface,
3851 DWORD flags, IDirectDrawSurface4 *reference)
3852 {
3853 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3854 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface4(reference);
3855
3856 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3857
3858 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
3859 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3860 }
3861
3862 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
3863 DWORD flags, IDirectDrawSurface3 *reference)
3864 {
3865 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3866 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface3(reference);
3867
3868 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3869
3870 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
3871 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3872 }
3873
3874 static HRESULT WINAPI ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2 *iface,
3875 DWORD flags, IDirectDrawSurface2 *reference)
3876 {
3877 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3878 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface2(reference);
3879
3880 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3881
3882 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
3883 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3884 }
3885
3886 static HRESULT WINAPI ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface *iface,
3887 DWORD flags, IDirectDrawSurface *reference)
3888 {
3889 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
3890 struct ddraw_surface *reference_impl = unsafe_impl_from_IDirectDrawSurface(reference);
3891
3892 TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3893
3894 return ddraw_surface7_UpdateOverlayZOrder(&surface->IDirectDrawSurface7_iface, flags,
3895 reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3896 }
3897
3898 /*****************************************************************************
3899 * IDirectDrawSurface7::GetDDInterface
3900 *
3901 * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
3902 * surface belongs to
3903 *
3904 * Params:
3905 * DD: Address to write the interface pointer to
3906 *
3907 * Returns:
3908 * DD_OK on success
3909 * DDERR_INVALIDPARAMS if DD is NULL
3910 *
3911 *****************************************************************************/
3912 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD)
3913 {
3914 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
3915
3916 TRACE("iface %p, ddraw %p.\n", iface, DD);
3917
3918 if(!DD)
3919 return DDERR_INVALIDPARAMS;
3920
3921 switch(This->version)
3922 {
3923 case 7:
3924 *DD = &This->ddraw->IDirectDraw7_iface;
3925 break;
3926
3927 case 4:
3928 *DD = &This->ddraw->IDirectDraw4_iface;
3929 break;
3930
3931 case 2:
3932 *DD = &This->ddraw->IDirectDraw2_iface;
3933 break;
3934
3935 case 1:
3936 *DD = &This->ddraw->IDirectDraw_iface;
3937 break;
3938
3939 }
3940 IUnknown_AddRef((IUnknown *)*DD);
3941
3942 return DD_OK;
3943 }
3944
3945 static HRESULT WINAPI ddraw_surface4_GetDDInterface(IDirectDrawSurface4 *iface, void **ddraw)
3946 {
3947 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3948
3949 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
3950
3951 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
3952 }
3953
3954 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw)
3955 {
3956 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
3957
3958 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
3959
3960 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
3961 }
3962
3963 static HRESULT WINAPI ddraw_surface2_GetDDInterface(IDirectDrawSurface2 *iface, void **ddraw)
3964 {
3965 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
3966
3967 TRACE("iface %p, ddraw %p.\n", iface, ddraw);
3968
3969 return ddraw_surface7_GetDDInterface(&surface->IDirectDrawSurface7_iface, ddraw);
3970 }
3971
3972 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface)
3973 {
3974 TRACE("iface %p.\n", iface);
3975
3976 return DD_OK;
3977 }
3978
3979 static HRESULT WINAPI ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4 *iface)
3980 {
3981 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
3982
3983 TRACE("iface %p.\n", iface);
3984
3985 return ddraw_surface7_ChangeUniquenessValue(&surface->IDirectDrawSurface7_iface);
3986 }
3987
3988 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue)
3989 {
3990 TRACE("iface %p, value %p.\n", iface, pValue);
3991
3992 *pValue = 0;
3993
3994 return DD_OK;
3995 }
3996
3997 static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *iface, DWORD *pValue)
3998 {
3999 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4000
4001 TRACE("iface %p, value %p.\n", iface, pValue);
4002
4003 return ddraw_surface7_GetUniquenessValue(&surface->IDirectDrawSurface7_iface, pValue);
4004 }
4005
4006 /*****************************************************************************
4007 * IDirectDrawSurface7::SetLOD
4008 *
4009 * Sets the level of detail of a texture
4010 *
4011 * Params:
4012 * MaxLOD: LOD to set
4013 *
4014 * Returns:
4015 * DD_OK on success
4016 * DDERR_INVALIDOBJECT if the surface is invalid for this method
4017 *
4018 *****************************************************************************/
4019 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD)
4020 {
4021 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4022 HRESULT hr;
4023
4024 TRACE("iface %p, lod %u.\n", iface, MaxLOD);
4025
4026 wined3d_mutex_lock();
4027 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
4028 {
4029 wined3d_mutex_unlock();
4030 return DDERR_INVALIDOBJECT;
4031 }
4032
4033 if (!surface->wined3d_texture)
4034 {
4035 ERR("The ddraw surface has no wined3d texture.\n");
4036 wined3d_mutex_unlock();
4037 return DDERR_INVALIDOBJECT;
4038 }
4039
4040 hr = wined3d_texture_set_lod(surface->wined3d_texture, MaxLOD);
4041 wined3d_mutex_unlock();
4042
4043 return hr;
4044 }
4045
4046 /*****************************************************************************
4047 * IDirectDrawSurface7::GetLOD
4048 *
4049 * Returns the level of detail of a Direct3D texture
4050 *
4051 * Params:
4052 * MaxLOD: Address to write the LOD to
4053 *
4054 * Returns:
4055 * DD_OK on success
4056 * DDERR_INVALIDPARAMS if MaxLOD is NULL
4057 * DDERR_INVALIDOBJECT if the surface is invalid for this method
4058 *
4059 *****************************************************************************/
4060 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD)
4061 {
4062 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4063
4064 TRACE("iface %p, lod %p.\n", iface, MaxLOD);
4065
4066 if(!MaxLOD)
4067 return DDERR_INVALIDPARAMS;
4068
4069 wined3d_mutex_lock();
4070 if (!(surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
4071 {
4072 wined3d_mutex_unlock();
4073 return DDERR_INVALIDOBJECT;
4074 }
4075
4076 *MaxLOD = wined3d_texture_get_lod(surface->wined3d_texture);
4077 wined3d_mutex_unlock();
4078
4079 return DD_OK;
4080 }
4081
4082 /*****************************************************************************
4083 * IDirectDrawSurface7::BltFast
4084 *
4085 * Performs a fast Blit.
4086 *
4087 * Params:
4088 * dstx: The x coordinate to blit to on the destination
4089 * dsty: The y coordinate to blit to on the destination
4090 * Source: The source surface
4091 * rsrc: The source rectangle
4092 * trans: Type of transfer. Some DDBLTFAST_* flags
4093 *
4094 * Returns:
4095 * DD_OK on success
4096 * For more details, see IWineD3DSurface::BltFast
4097 *
4098 *****************************************************************************/
4099 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_BltFast(IDirectDrawSurface7 *iface, DWORD dstx, DWORD dsty,
4100 IDirectDrawSurface7 *Source, RECT *rsrc, DWORD trans)
4101 {
4102 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4103 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(Source);
4104 DWORD src_w, src_h, dst_w, dst_h;
4105 HRESULT hr = DD_OK;
4106 DWORD flags = 0;
4107 RECT dst_rect;
4108
4109 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4110 iface, dstx, dsty, Source, wine_dbgstr_rect(rsrc), trans);
4111
4112 dst_w = This->surface_desc.dwWidth;
4113 dst_h = This->surface_desc.dwHeight;
4114
4115 /* Source must be != NULL, This is not checked by windows. Windows happily throws a 0xc0000005
4116 * in that case
4117 */
4118 if(rsrc)
4119 {
4120 src_w = rsrc->right - rsrc->left;
4121 src_h = rsrc->bottom - rsrc->top;
4122 }
4123 else
4124 {
4125 src_w = src->surface_desc.dwWidth;
4126 src_h = src->surface_desc.dwHeight;
4127 }
4128
4129 if (src_w > dst_w || dstx > dst_w - src_w
4130 || src_h > dst_h || dsty > dst_h - src_h)
4131 {
4132 WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
4133 return DDERR_INVALIDRECT;
4134 }
4135
4136 SetRect(&dst_rect, dstx, dsty, dstx + src_w, dsty + src_h);
4137 if (trans & DDBLTFAST_SRCCOLORKEY)
4138 flags |= WINEDDBLT_KEYSRC;
4139 if (trans & DDBLTFAST_DESTCOLORKEY)
4140 flags |= WINEDDBLT_KEYDEST;
4141 if (trans & DDBLTFAST_WAIT)
4142 flags |= WINEDDBLT_WAIT;
4143 if (trans & DDBLTFAST_DONOTWAIT)
4144 flags |= WINEDDBLT_DONOTWAIT;
4145
4146 wined3d_mutex_lock();
4147 if (This->clipper)
4148 {
4149 wined3d_mutex_unlock();
4150 WARN("Destination surface has a clipper set, returning DDERR_BLTFASTCANTCLIP.\n");
4151 return DDERR_BLTFASTCANTCLIP;
4152 }
4153
4154 if (src->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4155 hr = ddraw_surface_update_frontbuffer(src, rsrc, TRUE);
4156 if (SUCCEEDED(hr))
4157 hr = wined3d_surface_blt(This->wined3d_surface, &dst_rect,
4158 src->wined3d_surface, rsrc, flags, NULL, WINED3D_TEXF_POINT);
4159 if (SUCCEEDED(hr) && (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
4160 hr = ddraw_surface_update_frontbuffer(This, &dst_rect, FALSE);
4161 wined3d_mutex_unlock();
4162
4163 switch(hr)
4164 {
4165 case WINED3DERR_NOTAVAILABLE: return DDERR_UNSUPPORTED;
4166 case WINED3DERR_WRONGTEXTUREFORMAT: return DDERR_INVALIDPIXELFORMAT;
4167 default: return hr;
4168 }
4169 }
4170
4171 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface4_BltFast(IDirectDrawSurface4 *iface, DWORD dst_x, DWORD dst_y,
4172 IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags)
4173 {
4174 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface4(iface);
4175 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface4(src_surface);
4176
4177 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4178 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4179
4180 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4181 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4182 }
4183
4184 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y,
4185 IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags)
4186 {
4187 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface3(iface);
4188 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
4189
4190 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4191 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4192
4193 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4194 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4195 }
4196
4197 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface2_BltFast(IDirectDrawSurface2 *iface, DWORD dst_x, DWORD dst_y,
4198 IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags)
4199 {
4200 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface2(iface);
4201 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
4202
4203 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4204 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4205
4206 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4207 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4208 }
4209
4210 static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_BltFast(IDirectDrawSurface *iface, DWORD dst_x, DWORD dst_y,
4211 IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags)
4212 {
4213 struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface(iface);
4214 struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
4215
4216 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
4217 iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
4218
4219 return ddraw_surface7_BltFast(&dst_impl->IDirectDrawSurface7_iface, dst_x, dst_y,
4220 src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
4221 }
4222
4223 /*****************************************************************************
4224 * IDirectDrawSurface7::GetClipper
4225 *
4226 * Returns the IDirectDrawClipper interface of the clipper assigned to this
4227 * surface
4228 *
4229 * Params:
4230 * Clipper: Address to store the interface pointer at
4231 *
4232 * Returns:
4233 * DD_OK on success
4234 * DDERR_INVALIDPARAMS if Clipper is NULL
4235 * DDERR_NOCLIPPERATTACHED if there's no clipper attached
4236 *
4237 *****************************************************************************/
4238 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **Clipper)
4239 {
4240 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4241
4242 TRACE("iface %p, clipper %p.\n", iface, Clipper);
4243
4244 if (!Clipper)
4245 return DDERR_INVALIDPARAMS;
4246
4247 wined3d_mutex_lock();
4248 if (!surface->clipper)
4249 {
4250 wined3d_mutex_unlock();
4251 return DDERR_NOCLIPPERATTACHED;
4252 }
4253
4254 *Clipper = (IDirectDrawClipper *)surface->clipper;
4255 IDirectDrawClipper_AddRef(*Clipper);
4256 wined3d_mutex_unlock();
4257
4258 return DD_OK;
4259 }
4260
4261 static HRESULT WINAPI ddraw_surface4_GetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper **clipper)
4262 {
4263 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4264
4265 TRACE("iface %p, clipper %p.\n", iface, clipper);
4266
4267 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4268 }
4269
4270 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper)
4271 {
4272 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4273
4274 TRACE("iface %p, clipper %p.\n", iface, clipper);
4275
4276 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4277 }
4278
4279 static HRESULT WINAPI ddraw_surface2_GetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper **clipper)
4280 {
4281 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4282
4283 TRACE("iface %p, clipper %p.\n", iface, clipper);
4284
4285 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4286 }
4287
4288 static HRESULT WINAPI ddraw_surface1_GetClipper(IDirectDrawSurface *iface, IDirectDrawClipper **clipper)
4289 {
4290 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4291
4292 TRACE("iface %p, clipper %p.\n", iface, clipper);
4293
4294 return ddraw_surface7_GetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4295 }
4296
4297 /*****************************************************************************
4298 * IDirectDrawSurface7::SetClipper
4299 *
4300 * Sets a clipper for the surface
4301 *
4302 * Params:
4303 * Clipper: IDirectDrawClipper interface of the clipper to set
4304 *
4305 * Returns:
4306 * DD_OK on success
4307 *
4308 *****************************************************************************/
4309 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface,
4310 IDirectDrawClipper *iclipper)
4311 {
4312 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4313 struct ddraw_clipper *clipper = unsafe_impl_from_IDirectDrawClipper(iclipper);
4314 struct ddraw_clipper *old_clipper = This->clipper;
4315 HWND clipWindow;
4316
4317 TRACE("iface %p, clipper %p.\n", iface, iclipper);
4318
4319 wined3d_mutex_lock();
4320 if (clipper == This->clipper)
4321 {
4322 wined3d_mutex_unlock();
4323 return DD_OK;
4324 }
4325
4326 This->clipper = clipper;
4327
4328 if (clipper != NULL)
4329 IDirectDrawClipper_AddRef(iclipper);
4330 if (old_clipper)
4331 IDirectDrawClipper_Release(&old_clipper->IDirectDrawClipper_iface);
4332
4333 if ((This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && This->ddraw->wined3d_swapchain)
4334 {
4335 clipWindow = NULL;
4336 if(clipper) {
4337 IDirectDrawClipper_GetHWnd(iclipper, &clipWindow);
4338 }
4339
4340 if (clipWindow)
4341 {
4342 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, clipWindow);
4343 ddraw_set_swapchain_window(This->ddraw, clipWindow);
4344 }
4345 else
4346 {
4347 wined3d_swapchain_set_window(This->ddraw->wined3d_swapchain, This->ddraw->d3d_window);
4348 ddraw_set_swapchain_window(This->ddraw, This->ddraw->dest_window);
4349 }
4350 }
4351
4352 wined3d_mutex_unlock();
4353
4354 return DD_OK;
4355 }
4356
4357 static HRESULT WINAPI ddraw_surface4_SetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper *clipper)
4358 {
4359 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4360
4361 TRACE("iface %p, clipper %p.\n", iface, clipper);
4362
4363 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4364 }
4365
4366 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper)
4367 {
4368 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4369
4370 TRACE("iface %p, clipper %p.\n", iface, clipper);
4371
4372 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4373 }
4374
4375 static HRESULT WINAPI ddraw_surface2_SetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper *clipper)
4376 {
4377 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4378
4379 TRACE("iface %p, clipper %p.\n", iface, clipper);
4380
4381 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4382 }
4383
4384 static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDirectDrawClipper *clipper)
4385 {
4386 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4387
4388 TRACE("iface %p, clipper %p.\n", iface, clipper);
4389
4390 return ddraw_surface7_SetClipper(&surface->IDirectDrawSurface7_iface, clipper);
4391 }
4392
4393 /*****************************************************************************
4394 * IDirectDrawSurface7::SetSurfaceDesc
4395 *
4396 * Sets the surface description. It can override the pixel format, the surface
4397 * memory, ...
4398 * It's not really tested.
4399 *
4400 * Params:
4401 * DDSD: Pointer to the new surface description to set
4402 * Flags: Some flags
4403 *
4404 * Returns:
4405 * DD_OK on success
4406 * DDERR_INVALIDPARAMS if DDSD is NULL
4407 *
4408 *****************************************************************************/
4409 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
4410 {
4411 struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface);
4412 HRESULT hr;
4413 const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH
4414 | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS;
4415 enum wined3d_format_id format_id;
4416 UINT pitch, width, height;
4417
4418 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags);
4419
4420 if (!DDSD)
4421 {
4422 WARN("DDSD is NULL, returning DDERR_INVALIDPARAMS\n");
4423 return DDERR_INVALIDPARAMS;
4424 }
4425 if (Flags)
4426 {
4427 WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags);
4428 return DDERR_INVALIDPARAMS;
4429 }
4430 if (!(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
4431 || This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE
4432 || This->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
4433 {
4434 WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n");
4435 return DDERR_INVALIDSURFACETYPE;
4436 }
4437
4438 /* Tests show that only LPSURFACE and PIXELFORMAT can be set, and LPSURFACE is required
4439 * for PIXELFORMAT to work */
4440 if (DDSD->dwFlags & ~allowed_flags)
4441 {
4442 WARN("Invalid flags (0x%08x) set, returning DDERR_INVALIDPARAMS\n", DDSD->dwFlags);
4443 return DDERR_INVALIDPARAMS;
4444 }
4445 if (!(DDSD->dwFlags & DDSD_LPSURFACE) || !DDSD->lpSurface)
4446 {
4447 WARN("DDSD_LPSURFACE is not set or lpSurface is NULL, returning DDERR_INVALIDPARAMS\n");
4448 return DDERR_INVALIDPARAMS;
4449 }
4450 if ((DDSD->dwFlags & DDSD_CAPS) && DDSD->ddsCaps.dwCaps)
4451 {
4452 WARN("DDSD_CAPS is set, returning DDERR_INVALIDCAPS.\n");
4453 return DDERR_INVALIDCAPS;
4454 }
4455 if (DDSD->dwFlags & DDSD_WIDTH)
4456 {
4457 if (!(DDSD->dwFlags & DDSD_PITCH))
4458 {
4459 WARN("DDSD_WIDTH is set, but DDSD_PITCH is not, returning DDERR_INVALIDPARAMS.\n");
4460 return DDERR_INVALIDPARAMS;
4461 }
4462 if (!DDSD->dwWidth || DDSD->u1.lPitch <= 0 || DDSD->u1.lPitch & 0x3)
4463 {
4464 WARN("Pitch is %d, width is %u, returning DDERR_INVALIDPARAMS.\n",
4465 DDSD->u1.lPitch, DDSD->dwWidth);
4466 return DDERR_INVALIDPARAMS;
4467 }
4468 if (DDSD->dwWidth != This->surface_desc.dwWidth)
4469 TRACE("Surface width changed from %u to %u.\n", This->surface_desc.dwWidth, DDSD->dwWidth);
4470 if (DDSD->u1.lPitch != This->surface_desc.u1.lPitch)
4471 TRACE("Surface pitch changed from %u to %u.\n", This->surface_desc.u1.lPitch, DDSD->u1.lPitch);
4472 pitch = DDSD->u1.lPitch;
4473 width = DDSD->dwWidth;
4474 }
4475 else if (DDSD->dwFlags & DDSD_PITCH)
4476 {
4477 WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n");
4478 return DDERR_INVALIDPARAMS;
4479 }
4480 else
4481 {
4482 pitch = This->surface_desc.u1.lPitch;
4483 width = This->surface_desc.dwWidth;
4484 }
4485
4486 if (DDSD->dwFlags & DDSD_HEIGHT)
4487 {
4488 if (!DDSD->dwHeight)
4489 {
4490 WARN("Height is 0, returning DDERR_INVALIDPARAMS.\n");
4491 return DDERR_INVALIDPARAMS;
4492 }
4493 if (DDSD->dwHeight != This->surface_desc.dwHeight)
4494 TRACE("Surface height changed from %u to %u.\n", This->surface_desc.dwHeight, DDSD->dwHeight);
4495 height = DDSD->dwHeight;
4496 }
4497 else
4498 {
4499 height = This->surface_desc.dwHeight;
4500 }
4501
4502 wined3d_mutex_lock();
4503 if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4504 {
4505 enum wined3d_format_id current_format_id;
4506 format_id = wined3dformat_from_ddrawformat(&DDSD->u4.ddpfPixelFormat);
4507
4508 if (format_id == WINED3DFMT_UNKNOWN)
4509 {
4510 ERR("Requested to set an unknown pixelformat\n");
4511 wined3d_mutex_unlock();
4512 return DDERR_INVALIDPARAMS;
4513 }
4514 current_format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
4515 if (format_id != current_format_id)
4516 TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id);
4517 }
4518 else
4519 {
4520 format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat);
4521 }
4522
4523 if (FAILED(hr = wined3d_texture_update_desc(This->wined3d_texture, width, height,
4524 format_id, WINED3D_MULTISAMPLE_NONE, 0, DDSD->lpSurface, pitch)))
4525 {
4526 WARN("Failed to update surface desc, hr %#x.\n", hr);
4527 wined3d_mutex_unlock();
4528 return hr_ddraw_from_wined3d(hr);
4529 }
4530
4531 if (DDSD->dwFlags & DDSD_WIDTH)
4532 This->surface_desc.dwWidth = width;
4533 if (DDSD->dwFlags & DDSD_PITCH)
4534 This->surface_desc.u1.lPitch = DDSD->u1.lPitch;
4535 if (DDSD->dwFlags & DDSD_HEIGHT)
4536 This->surface_desc.dwHeight = height;
4537 if (DDSD->dwFlags & DDSD_PIXELFORMAT)
4538 This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
4539
4540 wined3d_mutex_unlock();
4541
4542 return DD_OK;
4543 }
4544
4545 static HRESULT WINAPI ddraw_surface4_SetSurfaceDesc(IDirectDrawSurface4 *iface,
4546 DDSURFACEDESC2 *surface_desc, DWORD flags)
4547 {
4548 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4549
4550 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4551
4552 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface,
4553 surface_desc, flags);
4554 }
4555
4556 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface,
4557 DDSURFACEDESC *surface_desc, DWORD flags)
4558 {
4559 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4560 DDSURFACEDESC2 surface_desc2;
4561
4562 TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4563
4564 if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
4565 return ddraw_surface7_SetSurfaceDesc(&surface->IDirectDrawSurface7_iface,
4566 surface_desc ? &surface_desc2 : NULL, flags);
4567 }
4568
4569 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **palette)
4570 {
4571 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4572 struct ddraw_palette *palette_impl;
4573 HRESULT hr = DD_OK;
4574
4575 TRACE("iface %p, palette %p.\n", iface, palette);
4576
4577 if (!palette)
4578 return DDERR_INVALIDPARAMS;
4579 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
4580 {
4581 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4582 return DDERR_SURFACELOST;
4583 }
4584
4585 wined3d_mutex_lock();
4586 if ((palette_impl = surface->palette))
4587 {
4588 *palette = &palette_impl->IDirectDrawPalette_iface;
4589 IDirectDrawPalette_AddRef(*palette);
4590 }
4591 else
4592 {
4593 *palette = NULL;
4594 hr = DDERR_NOPALETTEATTACHED;
4595 }
4596 wined3d_mutex_unlock();
4597
4598 return hr;
4599 }
4600
4601 static HRESULT WINAPI ddraw_surface4_GetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette **palette)
4602 {
4603 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4604
4605 TRACE("iface %p, palette %p.\n", iface, palette);
4606
4607 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4608 }
4609
4610 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette)
4611 {
4612 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4613
4614 TRACE("iface %p, palette %p.\n", iface, palette);
4615
4616 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4617 }
4618
4619 static HRESULT WINAPI ddraw_surface2_GetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette **palette)
4620 {
4621 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4622
4623 TRACE("iface %p, palette %p.\n", iface, palette);
4624
4625 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4626 }
4627
4628 static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDirectDrawPalette **palette)
4629 {
4630 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4631
4632 TRACE("iface %p, palette %p.\n", iface, palette);
4633
4634 return ddraw_surface7_GetPalette(&surface->IDirectDrawSurface7_iface, palette);
4635 }
4636
4637 static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD flags, DDCOLORKEY *color_key)
4638 {
4639 DDCOLORKEY fixed_color_key;
4640 HRESULT hr = WINED3D_OK;
4641
4642 if (flags & DDCKEY_COLORSPACE)
4643 {
4644 if (color_key && color_key->dwColorSpaceLowValue != color_key->dwColorSpaceHighValue)
4645 {
4646 WARN("Range color keys are not supported, returning DDERR_NOCOLORKEYHW.\n");
4647 return DDERR_NOCOLORKEYHW;
4648 }
4649 flags &= ~DDCKEY_COLORSPACE;
4650 }
4651
4652 wined3d_mutex_lock();
4653
4654 if (color_key)
4655 {
4656 fixed_color_key.dwColorSpaceLowValue = fixed_color_key.dwColorSpaceHighValue = color_key->dwColorSpaceLowValue;
4657 switch (flags & ~DDCKEY_COLORSPACE)
4658 {
4659 case DDCKEY_DESTBLT:
4660 surface->surface_desc.ddckCKDestBlt = fixed_color_key;
4661 surface->surface_desc.dwFlags |= DDSD_CKDESTBLT;
4662 break;
4663
4664 case DDCKEY_DESTOVERLAY:
4665 surface->surface_desc.u3.ddckCKDestOverlay = fixed_color_key;
4666 surface->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
4667 break;
4668
4669 case DDCKEY_SRCOVERLAY:
4670 surface->surface_desc.ddckCKSrcOverlay = fixed_color_key;
4671 surface->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
4672 break;
4673
4674 case DDCKEY_SRCBLT:
4675 surface->surface_desc.ddckCKSrcBlt = fixed_color_key;
4676 surface->surface_desc.dwFlags |= DDSD_CKSRCBLT;
4677 break;
4678
4679 default:
4680 wined3d_mutex_unlock();
4681 return DDERR_INVALIDPARAMS;
4682 }
4683 }
4684 else
4685 {
4686 switch (flags & ~DDCKEY_COLORSPACE)
4687 {
4688 case DDCKEY_DESTBLT:
4689 surface->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
4690 break;
4691
4692 case DDCKEY_DESTOVERLAY:
4693 surface->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
4694 break;
4695
4696 case DDCKEY_SRCOVERLAY:
4697 surface->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
4698 break;
4699
4700 case DDCKEY_SRCBLT:
4701 surface->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
4702 break;
4703
4704 default:
4705 wined3d_mutex_unlock();
4706 return DDERR_INVALIDPARAMS;
4707 }
4708 }
4709
4710 if (surface->wined3d_texture)
4711 hr = wined3d_texture_set_color_key(surface->wined3d_texture, flags,
4712 color_key ? (struct wined3d_color_key *)&fixed_color_key : NULL);
4713
4714 wined3d_mutex_unlock();
4715
4716 return hr_ddraw_from_wined3d(hr);
4717 }
4718
4719 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD flags, DDCOLORKEY *color_key)
4720 {
4721 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4722
4723 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4724
4725 wined3d_mutex_lock();
4726 if (!surface->wined3d_texture)
4727 {
4728 wined3d_mutex_unlock();
4729 return DDERR_NOTONMIPMAPSUBLEVEL;
4730 }
4731 wined3d_mutex_unlock();
4732
4733 return ddraw_surface_set_color_key(surface, flags, color_key);
4734 }
4735
4736 static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
4737 {
4738 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4739
4740 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4741
4742 return ddraw_surface_set_color_key(surface, flags, color_key);
4743 }
4744
4745 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
4746 {
4747 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4748
4749 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4750
4751 return ddraw_surface_set_color_key(surface, flags, color_key);
4752 }
4753
4754 static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
4755 {
4756 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4757
4758 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4759
4760 return ddraw_surface_set_color_key(surface, flags, color_key);
4761 }
4762
4763 static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
4764 {
4765 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4766
4767 TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4768
4769 return ddraw_surface_set_color_key(surface, flags, color_key);
4770 }
4771
4772 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *palette)
4773 {
4774 struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface);
4775
4776 TRACE("iface %p, palette %p.\n", iface, palette);
4777
4778 if (surface->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
4779 return DDERR_NOTONMIPMAPSUBLEVEL;
4780 if (IDirectDrawSurface7_IsLost(iface) == DDERR_SURFACELOST)
4781 {
4782 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4783 return DDERR_SURFACELOST;
4784 }
4785
4786 return ddraw_surface_set_palette(surface, palette);
4787 }
4788
4789 static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette *palette)
4790 {
4791 struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface);
4792
4793 TRACE("iface %p, palette %p.\n", iface, palette);
4794
4795 if (IDirectDrawSurface4_IsLost(iface) == DDERR_SURFACELOST)
4796 {
4797 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4798 return DDERR_SURFACELOST;
4799 }
4800
4801 return ddraw_surface_set_palette(surface, palette);
4802 }
4803
4804 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette)
4805 {
4806 struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface);
4807
4808 TRACE("iface %p, palette %p.\n", iface, palette);
4809
4810 if (IDirectDrawSurface3_IsLost(iface) == DDERR_SURFACELOST)
4811 {
4812 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4813 return DDERR_SURFACELOST;
4814 }
4815
4816 return ddraw_surface_set_palette(surface, palette);
4817 }
4818
4819 static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette *palette)
4820 {
4821 struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface);
4822
4823 TRACE("iface %p, palette %p.\n", iface, palette);
4824
4825 if (IDirectDrawSurface2_IsLost(iface) == DDERR_SURFACELOST)
4826 {
4827 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4828 return DDERR_SURFACELOST;
4829 }
4830
4831 return ddraw_surface_set_palette(surface, palette);
4832 }
4833
4834 static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDirectDrawPalette *palette)
4835 {
4836 struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface);
4837
4838 TRACE("iface %p, palette %p.\n", iface, palette);
4839
4840 if (IDirectDrawSurface_IsLost(iface) == DDERR_SURFACELOST)
4841 {
4842 WARN("Surface lost, returning DDERR_SURFACELOST.\n");
4843 return DDERR_SURFACELOST;
4844 }
4845
4846 return ddraw_surface_set_palette(surface, palette);
4847 }
4848
4849 /**********************************************************
4850 * IDirectDrawGammaControl::GetGammaRamp
4851 *
4852 * Returns the current gamma ramp for a surface
4853 *
4854 * Params:
4855 * flags: Ignored
4856 * gamma_ramp: Address to write the ramp to
4857 *
4858 * Returns:
4859 * DD_OK on success
4860 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
4861 *
4862 **********************************************************/
4863 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface,
4864 DWORD flags, DDGAMMARAMP *gamma_ramp)
4865 {
4866 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
4867
4868 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
4869
4870 if (!gamma_ramp)
4871 {
4872 WARN("Invalid gamma_ramp passed.\n");
4873 return DDERR_INVALIDPARAMS;
4874 }
4875
4876 wined3d_mutex_lock();
4877 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4878 {
4879 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
4880 wined3d_device_get_gamma_ramp(surface->ddraw->wined3d_device, 0, (struct wined3d_gamma_ramp *)gamma_ramp);
4881 }
4882 else
4883 {
4884 ERR("Not implemented for non-primary surfaces.\n");
4885 }
4886 wined3d_mutex_unlock();
4887
4888 return DD_OK;
4889 }
4890
4891 /**********************************************************
4892 * IDirectDrawGammaControl::SetGammaRamp
4893 *
4894 * Sets the red, green and blue gamma ramps for
4895 *
4896 * Params:
4897 * flags: Can be DDSGR_CALIBRATE to request calibration
4898 * gamma_ramp: Structure containing the new gamma ramp
4899 *
4900 * Returns:
4901 * DD_OK on success
4902 * DDERR_INVALIDPARAMS if gamma_ramp is NULL
4903 *
4904 **********************************************************/
4905 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface,
4906 DWORD flags, DDGAMMARAMP *gamma_ramp)
4907 {
4908 struct ddraw_surface *surface = impl_from_IDirectDrawGammaControl(iface);
4909
4910 TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
4911
4912 if (!gamma_ramp)
4913 {
4914 WARN("Invalid gamma_ramp passed.\n");
4915 return DDERR_INVALIDPARAMS;
4916 }
4917
4918 wined3d_mutex_lock();
4919 if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4920 {
4921 /* Note: DDGAMMARAMP is compatible with struct wined3d_gamma_ramp. */
4922 wined3d_device_set_gamma_ramp(surface->ddraw->wined3d_device,
4923 0, flags, (struct wined3d_gamma_ramp *)gamma_ramp);
4924 }
4925 else
4926 {
4927 ERR("Not implemented for non-primary surfaces.\n");
4928 }
4929 wined3d_mutex_unlock();
4930
4931 return DD_OK;
4932 }
4933
4934 /*****************************************************************************
4935 * IDirect3DTexture2::PaletteChanged
4936 *
4937 * Informs the texture about a palette change
4938 *
4939 * Params:
4940 * start: Start index of the change
4941 * count: The number of changed entries
4942 *
4943 * Returns
4944 * D3D_OK, because it's a stub
4945 *
4946 *****************************************************************************/
4947 static HRESULT WINAPI d3d_texture2_PaletteChanged(IDirect3DTexture2 *iface, DWORD start, DWORD count)
4948 {
4949 FIXME("iface %p, start %u, count %u stub!\n", iface, start, count);
4950
4951 return D3D_OK;
4952 }
4953
4954 static HRESULT WINAPI d3d_texture1_PaletteChanged(IDirect3DTexture *iface, DWORD start, DWORD count)
4955 {
4956 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
4957
4958 TRACE("iface %p, start %u, count %u.\n", iface, start, count);
4959
4960 return d3d_texture2_PaletteChanged(&surface->IDirect3DTexture2_iface, start, count);
4961 }
4962
4963 /*****************************************************************************
4964 * IDirect3DTexture::Unload
4965 *
4966 * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
4967 *
4968 *
4969 * Returns:
4970 * DDERR_UNSUPPORTED
4971 *
4972 *****************************************************************************/
4973 static HRESULT WINAPI d3d_texture1_Unload(IDirect3DTexture *iface)
4974 {
4975 WARN("iface %p. Not implemented.\n", iface);
4976
4977 return DDERR_UNSUPPORTED;
4978 }
4979
4980 /*****************************************************************************
4981 * IDirect3DTexture2::GetHandle
4982 *
4983 * Returns handle for the texture. At the moment, the interface
4984 * to the IWineD3DTexture is used.
4985 *
4986 * Params:
4987 * device: Device this handle is assigned to
4988 * handle: Address to store the handle at.
4989 *
4990 * Returns:
4991 * D3D_OK
4992 *
4993 *****************************************************************************/
4994 static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface,
4995 IDirect3DDevice2 *device, D3DTEXTUREHANDLE *handle)
4996 {
4997 struct ddraw_surface *surface = impl_from_IDirect3DTexture2(iface);
4998 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice2(device);
4999
5000 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
5001
5002 wined3d_mutex_lock();
5003
5004 if (!surface->Handle)
5005 {
5006 DWORD h = ddraw_allocate_handle(&device_impl->handle_table, surface, DDRAW_HANDLE_SURFACE);
5007 if (h == DDRAW_INVALID_HANDLE)
5008 {
5009 ERR("Failed to allocate a texture handle.\n");
5010 wined3d_mutex_unlock();
5011 return DDERR_OUTOFMEMORY;
5012 }
5013
5014 surface->Handle = h + 1;
5015 }
5016
5017 TRACE("Returning handle %08x.\n", surface->Handle);
5018 *handle = surface->Handle;
5019
5020 wined3d_mutex_unlock();
5021
5022 return D3D_OK;
5023 }
5024
5025 static HRESULT WINAPI d3d_texture1_GetHandle(IDirect3DTexture *iface,
5026 IDirect3DDevice *device, D3DTEXTUREHANDLE *handle)
5027 {
5028 struct ddraw_surface *surface = impl_from_IDirect3DTexture(iface);
5029 struct d3d_device *device_impl = unsafe_impl_from_IDirect3DDevice(device);
5030
5031 TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
5032
5033 return d3d_texture2_GetHandle(&surface->IDirect3DTexture2_iface,
5034 device_impl ? &device_impl->IDirect3DDevice2_iface : NULL, handle);
5035 }
5036
5037 /*****************************************************************************
5038 * get_sub_mimaplevel
5039 *
5040 * Helper function that returns the next mipmap level
5041 *
5042 * tex_ptr: Surface of which to return the next level
5043 *
5044 *****************************************************************************/
5045 static struct ddraw_surface *get_sub_mimaplevel(struct ddraw_surface *surface)
5046 {
5047 /* Now go down the mipmap chain to the next surface */
5048 static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, {0} };
5049 IDirectDrawSurface7 *next_level;
5050 HRESULT hr;
5051
5052 hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, &mipmap_caps, &next_level);
5053 if (FAILED(hr)) return NULL;
5054
5055 ddraw_surface7_Release(next_level);
5056
5057 return impl_from_IDirectDrawSurface7(next_level);
5058 }
5059
5060 static BOOL compare_format(DDPIXELFORMAT *format1, DDPIXELFORMAT *format2)
5061 {
5062 if ((format1->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC)) !=
5063 (format2->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_FOURCC)))
5064 return FALSE;
5065
5066 if (format1->dwFlags & (DDPF_RGB|DDPF_YUV))
5067 {
5068 if (!(format1->dwFlags & DDPF_ALPHA))
5069 {
5070 /* The RGB and YUV bits are stored in the same fields */
5071 if (format1->u1.dwRGBBitCount != format2->u1.dwRGBBitCount)
5072 return FALSE;
5073
5074 if (format1->u2.dwRBitMask != format2->u2.dwRBitMask)
5075 return FALSE;
5076
5077 if (format1->u3.dwGBitMask != format2->u3.dwGBitMask)
5078 return FALSE;
5079
5080 if (format1->u4.dwBBitMask != format2->u4.dwBBitMask)
5081 return FALSE;
5082 }
5083
5084 if (format1->dwFlags & (DDPF_ALPHAPIXELS | DDPF_ALPHA))
5085 {
5086 if (format1->u5.dwRGBAlphaBitMask != format2->u5.dwRGBAlphaBitMask)
5087 return FALSE;
5088 }
5089 }
5090
5091 if (format1->dwFlags & DDPF_FOURCC)
5092 {
5093 if (format1->dwFourCC != format2->dwFourCC)
5094 return FALSE;
5095 }
5096
5097 return TRUE;
5098 }
5099
5100 /*****************************************************************************
5101 * IDirect3DTexture2::Load
5102 *
5103 * Loads a texture created with the DDSCAPS_ALLOCONLOAD
5104 *
5105 * This function isn't relayed to WineD3D because the whole interface is
5106 * implemented in DDraw only. For speed improvements an implementation which
5107 * takes OpenGL more into account could be placed into WineD3D.
5108 *
5109 * Params:
5110 * src_texture: Address of the texture to load
5111 *
5112 * Returns:
5113 * D3D_OK on success
5114 * D3DERR_TEXTURE_LOAD_FAILED.
5115 *
5116 *****************************************************************************/
5117 static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTexture2 *src_texture)
5118 {
5119 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture2(iface);
5120 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture);
5121 HRESULT hr;
5122
5123 TRACE("iface %p, src_texture %p.\n", iface, src_texture);
5124
5125 if (src_surface == dst_surface)
5126 {
5127 TRACE("copying surface %p to surface %p, why?\n", src_surface, dst_surface);
5128 return D3D_OK;
5129 }
5130
5131 wined3d_mutex_lock();
5132
5133 for (;;)
5134 {
5135 DDSURFACEDESC *src_desc = (DDSURFACEDESC *)&src_surface->surface_desc;
5136
5137 TRACE("Copying surface %p to surface %p.\n", src_surface, dst_surface);
5138
5139 if (compare_format(&src_surface->surface_desc.u4.ddpfPixelFormat,
5140 &dst_surface->surface_desc.u4.ddpfPixelFormat))
5141 {
5142 struct ddraw_palette *dst_pal, *src_pal;
5143
5144 /* Get the palettes */
5145 dst_pal = dst_surface->palette;
5146 src_pal = src_surface->palette;
5147
5148 if (src_pal)
5149 {
5150 PALETTEENTRY palent[256];
5151
5152 if (!dst_pal)
5153 {
5154 wined3d_mutex_unlock();
5155 return DDERR_NOPALETTEATTACHED;
5156 }
5157 IDirectDrawPalette_GetEntries(&src_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
5158 IDirectDrawPalette_SetEntries(&dst_pal->IDirectDrawPalette_iface, 0, 0, 256, palent);
5159 }
5160
5161 if (src_desc->dwFlags & DDSD_CKSRCBLT)
5162 {
5163 IDirectDrawSurface7_SetColorKey(&dst_surface->IDirectDrawSurface7_iface,
5164 DDCKEY_SRCBLT, &src_desc->ddckCKSrcBlt);
5165 }
5166 }
5167 else
5168 {
5169 if (src_desc->dwFlags & DDSD_CKSRCBLT)
5170 return E_FAIL;
5171 }
5172
5173 /* Suppress the ALLOCONLOAD flag */
5174 dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
5175
5176 hr = wined3d_surface_blt(dst_surface->wined3d_surface, NULL, src_surface->wined3d_surface,
5177 NULL, 0, NULL, WINED3D_TEXF_LINEAR);
5178 if (FAILED(hr))
5179 {
5180 ERR("Failed to blit surface, hr %#x.\n", hr);
5181 wined3d_mutex_unlock();
5182 return hr;
5183 }
5184
5185 if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5186 src_surface = get_sub_mimaplevel(src_surface);
5187 else
5188 src_surface = NULL;
5189
5190 if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5191 dst_surface = get_sub_mimaplevel(dst_surface);
5192 else
5193 dst_surface = NULL;
5194
5195 if (src_surface && !dst_surface)
5196 return DDERR_NOTFOUND;
5197
5198 if (!src_surface || !dst_surface)
5199 break;
5200 }
5201
5202 wined3d_mutex_unlock();
5203
5204 return hr;
5205 }
5206
5207 static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTexture *src_texture)
5208 {
5209 struct ddraw_surface *dst_surface = impl_from_IDirect3DTexture(iface);
5210 struct ddraw_surface *src_surface = unsafe_impl_from_IDirect3DTexture(src_texture);
5211
5212 TRACE("iface %p, src_texture %p.\n", iface, src_texture);
5213
5214 return d3d_texture2_Load(&dst_surface->IDirect3DTexture2_iface,
5215 src_surface ? &src_surface->IDirect3DTexture2_iface : NULL);
5216 }
5217
5218 /*****************************************************************************
5219 * The VTable
5220 *****************************************************************************/
5221
5222 static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl =
5223 {
5224 /* IUnknown */
5225 ddraw_surface7_QueryInterface,
5226 ddraw_surface7_AddRef,
5227 ddraw_surface7_Release,
5228 /* IDirectDrawSurface */
5229 ddraw_surface7_AddAttachedSurface,
5230 ddraw_surface7_AddOverlayDirtyRect,
5231 ddraw_surface7_Blt,
5232 ddraw_surface7_BltBatch,
5233 ddraw_surface7_BltFast,
5234 ddraw_surface7_DeleteAttachedSurface,
5235 ddraw_surface7_EnumAttachedSurfaces,
5236 ddraw_surface7_EnumOverlayZOrders,
5237 ddraw_surface7_Flip,
5238 ddraw_surface7_GetAttachedSurface,
5239 ddraw_surface7_GetBltStatus,
5240 ddraw_surface7_GetCaps,
5241 ddraw_surface7_GetClipper,
5242 ddraw_surface7_GetColorKey,
5243 ddraw_surface7_GetDC,
5244 ddraw_surface7_GetFlipStatus,
5245 ddraw_surface7_GetOverlayPosition,
5246 ddraw_surface7_GetPalette,
5247 ddraw_surface7_GetPixelFormat,
5248 ddraw_surface7_GetSurfaceDesc,
5249 ddraw_surface7_Initialize,
5250 ddraw_surface7_IsLost,
5251 ddraw_surface7_Lock,
5252 ddraw_surface7_ReleaseDC,
5253 ddraw_surface7_Restore,
5254 ddraw_surface7_SetClipper,
5255 ddraw_surface7_SetColorKey,
5256 ddraw_surface7_SetOverlayPosition,
5257 ddraw_surface7_SetPalette,
5258 ddraw_surface7_Unlock,
5259 ddraw_surface7_UpdateOverlay,
5260 ddraw_surface7_UpdateOverlayDisplay,
5261 ddraw_surface7_UpdateOverlayZOrder,
5262 /* IDirectDrawSurface2 */
5263 ddraw_surface7_GetDDInterface,
5264 ddraw_surface7_PageLock,
5265 ddraw_surface7_PageUnlock,
5266 /* IDirectDrawSurface3 */
5267 ddraw_surface7_SetSurfaceDesc,
5268 /* IDirectDrawSurface4 */
5269 ddraw_surface7_SetPrivateData,
5270 ddraw_surface7_GetPrivateData,
5271 ddraw_surface7_FreePrivateData,
5272 ddraw_surface7_GetUniquenessValue,
5273 ddraw_surface7_ChangeUniquenessValue,
5274 /* IDirectDrawSurface7 */
5275 ddraw_surface7_SetPriority,
5276 ddraw_surface7_GetPriority,
5277 ddraw_surface7_SetLOD,
5278 ddraw_surface7_GetLOD,
5279 };
5280
5281 static const struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl =
5282 {
5283 /* IUnknown */
5284 ddraw_surface4_QueryInterface,
5285 ddraw_surface4_AddRef,
5286 ddraw_surface4_Release,
5287 /* IDirectDrawSurface */
5288 ddraw_surface4_AddAttachedSurface,
5289 ddraw_surface4_AddOverlayDirtyRect,
5290 ddraw_surface4_Blt,
5291 ddraw_surface4_BltBatch,
5292 ddraw_surface4_BltFast,
5293 ddraw_surface4_DeleteAttachedSurface,
5294 ddraw_surface4_EnumAttachedSurfaces,
5295 ddraw_surface4_EnumOverlayZOrders,
5296 ddraw_surface4_Flip,
5297 ddraw_surface4_GetAttachedSurface,
5298 ddraw_surface4_GetBltStatus,
5299 ddraw_surface4_GetCaps,
5300 ddraw_surface4_GetClipper,
5301 ddraw_surface4_GetColorKey,
5302 ddraw_surface4_GetDC,
5303 ddraw_surface4_GetFlipStatus,
5304 ddraw_surface4_GetOverlayPosition,
5305 ddraw_surface4_GetPalette,
5306 ddraw_surface4_GetPixelFormat,
5307 ddraw_surface4_GetSurfaceDesc,
5308 ddraw_surface4_Initialize,
5309 ddraw_surface4_IsLost,
5310 ddraw_surface4_Lock,
5311 ddraw_surface4_ReleaseDC,
5312 ddraw_surface4_Restore,
5313 ddraw_surface4_SetClipper,
5314 ddraw_surface4_SetColorKey,
5315 ddraw_surface4_SetOverlayPosition,
5316 ddraw_surface4_SetPalette,
5317 ddraw_surface4_Unlock,
5318 ddraw_surface4_UpdateOverlay,
5319 ddraw_surface4_UpdateOverlayDisplay,
5320 ddraw_surface4_UpdateOverlayZOrder,
5321 /* IDirectDrawSurface2 */
5322 ddraw_surface4_GetDDInterface,
5323 ddraw_surface4_PageLock,
5324 ddraw_surface4_PageUnlock,
5325 /* IDirectDrawSurface3 */
5326 ddraw_surface4_SetSurfaceDesc,
5327 /* IDirectDrawSurface4 */
5328 ddraw_surface4_SetPrivateData,
5329 ddraw_surface4_GetPrivateData,
5330 ddraw_surface4_FreePrivateData,
5331 ddraw_surface4_GetUniquenessValue,
5332 ddraw_surface4_ChangeUniquenessValue,
5333 };
5334
5335 static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl =
5336 {
5337 /* IUnknown */
5338 ddraw_surface3_QueryInterface,
5339 ddraw_surface3_AddRef,
5340 ddraw_surface3_Release,
5341 /* IDirectDrawSurface */
5342 ddraw_surface3_AddAttachedSurface,
5343 ddraw_surface3_AddOverlayDirtyRect,
5344 ddraw_surface3_Blt,
5345 ddraw_surface3_BltBatch,
5346 ddraw_surface3_BltFast,
5347 ddraw_surface3_DeleteAttachedSurface,
5348 ddraw_surface3_EnumAttachedSurfaces,
5349 ddraw_surface3_EnumOverlayZOrders,
5350 ddraw_surface3_Flip,
5351 ddraw_surface3_GetAttachedSurface,
5352 ddraw_surface3_GetBltStatus,
5353 ddraw_surface3_GetCaps,
5354 ddraw_surface3_GetClipper,
5355 ddraw_surface3_GetColorKey,
5356 ddraw_surface3_GetDC,
5357 ddraw_surface3_GetFlipStatus,
5358 ddraw_surface3_GetOverlayPosition,
5359 ddraw_surface3_GetPalette,
5360 ddraw_surface3_GetPixelFormat,
5361 ddraw_surface3_GetSurfaceDesc,
5362 ddraw_surface3_Initialize,
5363 ddraw_surface3_IsLost,
5364 ddraw_surface3_Lock,
5365 ddraw_surface3_ReleaseDC,
5366 ddraw_surface3_Restore,
5367 ddraw_surface3_SetClipper,
5368 ddraw_surface3_SetColorKey,
5369 ddraw_surface3_SetOverlayPosition,
5370 ddraw_surface3_SetPalette,
5371 ddraw_surface3_Unlock,
5372 ddraw_surface3_UpdateOverlay,
5373 ddraw_surface3_UpdateOverlayDisplay,
5374 ddraw_surface3_UpdateOverlayZOrder,
5375 /* IDirectDrawSurface2 */
5376 ddraw_surface3_GetDDInterface,
5377 ddraw_surface3_PageLock,
5378 ddraw_surface3_PageUnlock,
5379 /* IDirectDrawSurface3 */
5380 ddraw_surface3_SetSurfaceDesc,
5381 };
5382
5383 static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
5384 {
5385 /* IUnknown */
5386 ddraw_surface2_QueryInterface,
5387 ddraw_surface2_AddRef,
5388 ddraw_surface2_Release,
5389 /* IDirectDrawSurface */
5390 ddraw_surface2_AddAttachedSurface,
5391 ddraw_surface2_AddOverlayDirtyRect,
5392 ddraw_surface2_Blt,
5393 ddraw_surface2_BltBatch,
5394 ddraw_surface2_BltFast,
5395 ddraw_surface2_DeleteAttachedSurface,
5396 ddraw_surface2_EnumAttachedSurfaces,
5397 ddraw_surface2_EnumOverlayZOrders,
5398 ddraw_surface2_Flip,
5399 ddraw_surface2_GetAttachedSurface,
5400 ddraw_surface2_GetBltStatus,
5401 ddraw_surface2_GetCaps,
5402 ddraw_surface2_GetClipper,
5403 ddraw_surface2_GetColorKey,
5404 ddraw_surface2_GetDC,
5405 ddraw_surface2_GetFlipStatus,
5406 ddraw_surface2_GetOverlayPosition,
5407 ddraw_surface2_GetPalette,
5408 ddraw_surface2_GetPixelFormat,
5409 ddraw_surface2_GetSurfaceDesc,
5410 ddraw_surface2_Initialize,
5411 ddraw_surface2_IsLost,
5412 ddraw_surface2_Lock,
5413 ddraw_surface2_ReleaseDC,
5414 ddraw_surface2_Restore,
5415 ddraw_surface2_SetClipper,
5416 ddraw_surface2_SetColorKey,
5417 ddraw_surface2_SetOverlayPosition,
5418 ddraw_surface2_SetPalette,
5419 ddraw_surface2_Unlock,
5420 ddraw_surface2_UpdateOverlay,
5421 ddraw_surface2_UpdateOverlayDisplay,
5422 ddraw_surface2_UpdateOverlayZOrder,
5423 /* IDirectDrawSurface2 */
5424 ddraw_surface2_GetDDInterface,
5425 ddraw_surface2_PageLock,
5426 ddraw_surface2_PageUnlock,
5427 };
5428
5429 static struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
5430 {
5431 /* IUnknown */
5432 ddraw_surface1_QueryInterface,
5433 ddraw_surface1_AddRef,
5434 ddraw_surface1_Release,
5435 /* IDirectDrawSurface */
5436 ddraw_surface1_AddAttachedSurface,
5437 ddraw_surface1_AddOverlayDirtyRect,
5438 ddraw_surface1_Blt,
5439 ddraw_surface1_BltBatch,
5440 ddraw_surface1_BltFast,
5441 ddraw_surface1_DeleteAttachedSurface,
5442 ddraw_surface1_EnumAttachedSurfaces,
5443 ddraw_surface1_EnumOverlayZOrders,
5444 ddraw_surface1_Flip,
5445 ddraw_surface1_GetAttachedSurface,
5446 ddraw_surface1_GetBltStatus,
5447 ddraw_surface1_GetCaps,
5448 ddraw_surface1_GetClipper,
5449 ddraw_surface1_GetColorKey,
5450 ddraw_surface1_GetDC,
5451 ddraw_surface1_GetFlipStatus,
5452 ddraw_surface1_GetOverlayPosition,
5453 ddraw_surface1_GetPalette,
5454 ddraw_surface1_GetPixelFormat,
5455 ddraw_surface1_GetSurfaceDesc,
5456 ddraw_surface1_Initialize,
5457 ddraw_surface1_IsLost,
5458 ddraw_surface1_Lock,
5459 ddraw_surface1_ReleaseDC,
5460 ddraw_surface1_Restore,
5461 ddraw_surface1_SetClipper,
5462 ddraw_surface1_SetColorKey,
5463 ddraw_surface1_SetOverlayPosition,
5464 ddraw_surface1_SetPalette,
5465 ddraw_surface1_Unlock,
5466 ddraw_surface1_UpdateOverlay,
5467 ddraw_surface1_UpdateOverlayDisplay,
5468 ddraw_surface1_UpdateOverlayZOrder,
5469 };
5470
5471 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl =
5472 {
5473 ddraw_gamma_control_QueryInterface,
5474 ddraw_gamma_control_AddRef,
5475 ddraw_gamma_control_Release,
5476 ddraw_gamma_control_GetGammaRamp,
5477 ddraw_gamma_control_SetGammaRamp,
5478 };
5479
5480 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl =
5481 {
5482 d3d_texture2_QueryInterface,
5483 d3d_texture2_AddRef,
5484 d3d_texture2_Release,
5485 d3d_texture2_GetHandle,
5486 d3d_texture2_PaletteChanged,
5487 d3d_texture2_Load,
5488 };
5489
5490 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl =
5491 {
5492 d3d_texture1_QueryInterface,
5493 d3d_texture1_AddRef,
5494 d3d_texture1_Release,
5495 d3d_texture1_Initialize,
5496 d3d_texture1_GetHandle,
5497 d3d_texture1_PaletteChanged,
5498 d3d_texture1_Load,
5499 d3d_texture1_Unload,
5500 };
5501
5502 /* Some games (e.g. Tomb Raider 3) pass the wrong version of the
5503 * IDirectDrawSurface interface to ddraw methods. */
5504 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 *iface)
5505 {
5506 if (!iface) return NULL;
5507 if (iface->lpVtbl != &ddraw_surface7_vtbl)
5508 {
5509 HRESULT hr = IDirectDrawSurface7_QueryInterface(iface, &IID_IDirectDrawSurface7, (void **)&iface);
5510 if (FAILED(hr))
5511 {
5512 WARN("Object %p doesn't expose interface IDirectDrawSurface7.\n", iface);
5513 return NULL;
5514 }
5515 IDirectDrawSurface7_Release(iface);
5516 }
5517 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface7_iface);
5518 }
5519
5520 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4 *iface)
5521 {
5522 if (!iface) return NULL;
5523 if (iface->lpVtbl != &ddraw_surface4_vtbl)
5524 {
5525 HRESULT hr = IDirectDrawSurface4_QueryInterface(iface, &IID_IDirectDrawSurface4, (void **)&iface);
5526 if (FAILED(hr))
5527 {
5528 WARN("Object %p doesn't expose interface IDirectDrawSurface4.\n", iface);
5529 return NULL;
5530 }
5531 IDirectDrawSurface4_Release(iface);
5532 }
5533 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface4_iface);
5534 }
5535
5536 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface)
5537 {
5538 if (!iface) return NULL;
5539 if (iface->lpVtbl != &ddraw_surface3_vtbl)
5540 {
5541 HRESULT hr = IDirectDrawSurface3_QueryInterface(iface, &IID_IDirectDrawSurface3, (void **)&iface);
5542 if (FAILED(hr))
5543 {
5544 WARN("Object %p doesn't expose interface IDirectDrawSurface3.\n", iface);
5545 return NULL;
5546 }
5547 IDirectDrawSurface3_Release(iface);
5548 }
5549 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface3_iface);
5550 }
5551
5552 static struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface)
5553 {
5554 if (!iface) return NULL;
5555 if (iface->lpVtbl != &ddraw_surface2_vtbl)
5556 {
5557 HRESULT hr = IDirectDrawSurface2_QueryInterface(iface, &IID_IDirectDrawSurface2, (void **)&iface);
5558 if (FAILED(hr))
5559 {
5560 WARN("Object %p doesn't expose interface IDirectDrawSurface2.\n", iface);
5561 return NULL;
5562 }
5563 IDirectDrawSurface2_Release(iface);
5564 }
5565 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface2_iface);
5566 }
5567
5568 struct ddraw_surface *unsafe_impl_from_IDirectDrawSurface(IDirectDrawSurface *iface)
5569 {
5570 if (!iface) return NULL;
5571 if (iface->lpVtbl != &ddraw_surface1_vtbl)
5572 {
5573 HRESULT hr = IDirectDrawSurface_QueryInterface(iface, &IID_IDirectDrawSurface, (void **)&iface);
5574 if (FAILED(hr))
5575 {
5576 WARN("Object %p doesn't expose interface IDirectDrawSurface.\n", iface);
5577 return NULL;
5578 }
5579 IDirectDrawSurface_Release(iface);
5580 }
5581 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirectDrawSurface_iface);
5582 }
5583
5584 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2 *iface)
5585 {
5586 if (!iface) return NULL;
5587 assert(iface->lpVtbl == &d3d_texture2_vtbl);
5588 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture2_iface);
5589 }
5590
5591 struct ddraw_surface *unsafe_impl_from_IDirect3DTexture(IDirect3DTexture *iface)
5592 {
5593 if (!iface) return NULL;
5594 assert(iface->lpVtbl == &d3d_texture1_vtbl);
5595 return CONTAINING_RECORD(iface, struct ddraw_surface, IDirect3DTexture_iface);
5596 }
5597
5598 static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent)
5599 {
5600 struct ddraw_surface *surface = parent;
5601
5602 TRACE("surface %p.\n", surface);
5603
5604 /* Check for attached surfaces and detach them. */
5605 if (surface->first_attached != surface)
5606 {
5607 /* Well, this shouldn't happen: The surface being attached is
5608 * referenced in AddAttachedSurface(), so it shouldn't be released
5609 * until DeleteAttachedSurface() is called, because the refcount is
5610 * held. It looks like the application released it often enough to
5611 * force this. */
5612 WARN("Surface is still attached to surface %p.\n", surface->first_attached);
5613
5614 /* The refcount will drop to -1 here */
5615 if (FAILED(ddraw_surface_delete_attached_surface(surface->first_attached, surface, surface->attached_iface)))
5616 ERR("DeleteAttachedSurface failed.\n");
5617 }
5618
5619 while (surface->next_attached)
5620 if (FAILED(ddraw_surface_delete_attached_surface(surface,
5621 surface->next_attached, surface->next_attached->attached_iface)))
5622 ERR("DeleteAttachedSurface failed.\n");
5623
5624 /* Having a texture handle set implies that the device still exists. */
5625 if (surface->Handle)
5626 ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE);
5627
5628 /* Reduce the ddraw surface count. */
5629 list_remove(&surface->surface_list_entry);
5630
5631 if (surface->clipper)
5632 IDirectDrawClipper_Release(&surface->clipper->IDirectDrawClipper_iface);
5633
5634 if (surface == surface->ddraw->primary)
5635 surface->ddraw->primary = NULL;
5636
5637 wined3d_private_store_cleanup(&surface->private_store);
5638
5639 HeapFree(GetProcessHeap(), 0, surface);
5640 }
5641
5642 static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
5643 {
5644 ddraw_surface_wined3d_object_destroyed,
5645 };
5646
5647 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent)
5648 {
5649 TRACE("parent %p.\n", parent);
5650
5651 HeapFree(GetProcessHeap(), 0, parent);
5652 }
5653
5654 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
5655 {
5656 ddraw_texture_wined3d_object_destroyed,
5657 };
5658
5659 static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource)
5660 {
5661 return DD_OK;
5662 }
5663
5664 HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
5665 struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version)
5666 {
5667 struct ddraw_surface *root, *mip, **attach;
5668 struct wined3d_resource_desc wined3d_desc;
5669 struct wined3d_texture *wined3d_texture;
5670 struct wined3d_resource *resource;
5671 struct wined3d_display_mode mode;
5672 DDSURFACEDESC2 *desc, *mip_desc;
5673 struct ddraw_texture *texture;
5674 UINT layers, levels, i, j;
5675 unsigned int pitch = 0;
5676 HRESULT hr;
5677
5678 TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p, version %u.\n",
5679 ddraw, surface_desc, surface, outer_unknown, version);
5680 if (TRACE_ON(ddraw))
5681 {
5682 TRACE("Requesting surface desc:\n");
5683 DDRAW_dump_surface_desc(surface_desc);
5684 }
5685
5686 if (outer_unknown)
5687 return CLASS_E_NOAGGREGATION;
5688
5689 if (!surface)
5690 return E_POINTER;
5691
5692 if (!(texture = HeapAlloc(GetProcessHeap(), 0, sizeof(*texture))))
5693 return E_OUTOFMEMORY;
5694
5695 texture->version = version;
5696 texture->surface_desc = *surface_desc;
5697 desc = &texture->surface_desc;
5698
5699 /* Ensure DDSD_CAPS is always set. */
5700 desc->dwFlags |= DDSD_CAPS;
5701
5702 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5703 {
5704 DWORD flippable = desc->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_COMPLEX);
5705
5706 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5707 {
5708 WARN("Tried to create a primary surface with DDSCAPS_TEXTURE.\n");
5709 HeapFree(GetProcessHeap(), 0, texture);
5710 return DDERR_INVALIDCAPS;
5711 }
5712
5713 if (flippable)
5714 {
5715 if (flippable != (DDSCAPS_FLIP | DDSCAPS_COMPLEX))
5716 {
5717 WARN("Tried to create a flippable primary surface without both DDSCAPS_FLIP and DDSCAPS_COMPLEX.\n");
5718 HeapFree(GetProcessHeap(), 0, texture);
5719 return DDERR_INVALIDCAPS;
5720 }
5721
5722 if (!(desc->dwFlags & DDSD_BACKBUFFERCOUNT) || !desc->u5.dwBackBufferCount)
5723 {
5724 WARN("Tried to create a flippable primary surface without any back buffers.\n");
5725 HeapFree(GetProcessHeap(), 0, texture);
5726 return DDERR_INVALIDCAPS;
5727 }
5728
5729 if (!(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
5730 {
5731 WARN("Tried to create a flippable primary surface without DDSCL_EXCLUSIVE.\n");
5732 HeapFree(GetProcessHeap(), 0, texture);
5733 return DDERR_NOEXCLUSIVEMODE;
5734 }
5735 }
5736 }
5737
5738 /* This is a special case in ddrawex, but not allowed in ddraw. */
5739 if ((desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5740 == (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5741 {
5742 WARN("Tried to create a surface in both system and video memory.\n");
5743 HeapFree(GetProcessHeap(), 0, texture);
5744 return DDERR_INVALIDCAPS;
5745 }
5746
5747 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES)
5748 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5749 {
5750 WARN("Cube map faces requested without cube map flag.\n");
5751 HeapFree(GetProcessHeap(), 0, texture);
5752 return DDERR_INVALIDCAPS;
5753 }
5754
5755 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5756 && !(desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES))
5757 {
5758 WARN("Cube map without faces requested.\n");
5759 HeapFree(GetProcessHeap(), 0, texture);
5760 return DDERR_INVALIDPARAMS;
5761 }
5762
5763 if ((desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5764 && (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
5765 FIXME("Partial cube maps not implemented.\n");
5766
5767 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
5768 {
5769 if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
5770 {
5771 WARN("DDSCAPS2_TEXTUREMANAGE used without DDSCAPS_TEXTURE, returning DDERR_INVALIDCAPS.\n");
5772 HeapFree(GetProcessHeap(), 0, texture);
5773 return DDERR_INVALIDCAPS;
5774 }
5775 if (desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5776 {
5777 WARN("DDSCAPS2_TEXTUREMANAGE used width DDSCAPS_VIDEOMEMORY "
5778 "or DDSCAPS_SYSTEMMEMORY, returning DDERR_INVALIDCAPS.\n");
5779 HeapFree(GetProcessHeap(), 0, texture);
5780 return DDERR_INVALIDCAPS;
5781 }
5782 }
5783
5784 if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
5785 {
5786 ERR("Failed to get display mode, hr %#x.\n", hr);
5787 HeapFree(GetProcessHeap(), 0, texture);
5788 return hr_ddraw_from_wined3d(hr);
5789 }
5790
5791 /* No pixelformat given? Use the current screen format. */
5792 if (!(desc->dwFlags & DDSD_PIXELFORMAT))
5793 {
5794 desc->dwFlags |= DDSD_PIXELFORMAT;
5795 desc->u4.ddpfPixelFormat.dwSize = sizeof(desc->u4.ddpfPixelFormat);
5796 ddrawformat_from_wined3dformat(&desc->u4.ddpfPixelFormat, mode.format_id);
5797 }
5798
5799 wined3d_desc.format = wined3dformat_from_ddrawformat(&desc->u4.ddpfPixelFormat);
5800 if (wined3d_desc.format == WINED3DFMT_UNKNOWN)
5801 {
5802 WARN("Unsupported / unknown pixelformat.\n");
5803 HeapFree(GetProcessHeap(), 0, texture);
5804 return DDERR_INVALIDPIXELFORMAT;
5805 }
5806
5807 /* No width or no height? Use the screen size. */
5808 if (!(desc->dwFlags & DDSD_WIDTH) || !(desc->dwFlags & DDSD_HEIGHT))
5809 {
5810 if (!(desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
5811 {
5812 WARN("No width / height specified.\n");
5813 HeapFree(GetProcessHeap(), 0, texture);
5814 return DDERR_INVALIDPARAMS;
5815 }
5816
5817 desc->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5818 desc->dwWidth = mode.width;
5819 desc->dwHeight = mode.height;
5820 }
5821
5822 if (!desc->dwWidth || !desc->dwHeight)
5823 {
5824 HeapFree(GetProcessHeap(), 0, texture);
5825 return DDERR_INVALIDPARAMS;
5826 }
5827
5828 if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5829 {
5830 /* The first surface is a front buffer, the back buffers are created
5831 * afterwards. */
5832 if (desc->ddsCaps.dwCaps & DDSCAPS_FLIP)
5833 desc->ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
5834 desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
5835 if (ddraw->cooperative_level & DDSCL_EXCLUSIVE)
5836 {
5837 struct wined3d_swapchain_desc swapchain_desc;
5838
5839 wined3d_swapchain_get_desc(ddraw->wined3d_swapchain, &swapchain_desc);
5840 swapchain_desc.backbuffer_width = mode.width;
5841 swapchain_desc.backbuffer_height = mode.height;
5842 swapchain_desc.backbuffer_format = mode.format_id;
5843
5844 if (FAILED(hr = wined3d_device_reset(ddraw->wined3d_device,
5845 &swapchain_desc, NULL, ddraw_reset_enum_callback, TRUE)))
5846 {
5847 ERR("Failed to reset device.\n");
5848 HeapFree(GetProcessHeap(), 0, texture);
5849 return hr_ddraw_from_wined3d(hr);
5850 }
5851 }
5852 }
5853
5854 wined3d_desc.multisample_type = WINED3D_MULTISAMPLE_NONE;
5855 wined3d_desc.multisample_quality = 0;
5856 wined3d_desc.usage = 0;
5857 wined3d_desc.pool = WINED3D_POOL_DEFAULT;
5858 wined3d_desc.width = desc->dwWidth;
5859 wined3d_desc.height = desc->dwHeight;
5860 wined3d_desc.depth = 1;
5861 wined3d_desc.size = 0;
5862
5863 if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && (ddraw->flags & DDRAW_NO3D))
5864 {
5865 WARN("The application requests a 3D capable surface, but the ddraw object was created without 3D support.\n");
5866 /* Do not fail surface creation, only fail 3D device creation. */
5867 }
5868
5869 /* Mipmap count fixes */
5870 if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5871 {
5872 if (desc->ddsCaps.dwCaps & DDSCAPS_COMPLEX)
5873 {
5874 if (desc->dwFlags & DDSD_MIPMAPCOUNT)
5875 {
5876 /* Mipmap count is given, should not be 0. */
5877 if (!desc->u2.dwMipMapCount)
5878 {
5879 HeapFree(GetProcessHeap(), 0, texture);
5880 return DDERR_INVALIDPARAMS;
5881 }
5882 }
5883 else
5884 {
5885 /* Undocumented feature: Create sublevels until either the
5886 * width or the height is 1. */
5887 desc->u2.dwMipMapCount = wined3d_log2i(min(desc->dwWidth, desc->dwHeight)) + 1;
5888 }
5889 }
5890 else
5891 {
5892 desc->u2.dwMipMapCount = 1;
5893 }
5894
5895 desc->dwFlags |= DDSD_MIPMAPCOUNT;
5896 levels = desc->u2.dwMipMapCount;
5897 }
5898 else
5899 {
5900 levels = 1;
5901 }
5902
5903 if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY)))
5904 {
5905 if (!(desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)))
5906 {
5907 enum wined3d_resource_type rtype;
5908 DWORD usage = 0;
5909
5910 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5911 rtype = WINED3D_RTYPE_CUBE_TEXTURE;
5912 else if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5913 rtype = WINED3D_RTYPE_TEXTURE;
5914 else
5915 rtype = WINED3D_RTYPE_SURFACE;
5916
5917 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
5918 usage = WINED3DUSAGE_DEPTHSTENCIL;
5919 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
5920 usage = WINED3DUSAGE_RENDERTARGET;
5921
5922 if (SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
5923 WINED3D_DEVICE_TYPE_HAL, mode.format_id, usage, rtype, wined3d_desc.format)))
5924 desc->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
5925 else
5926 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
5927 }
5928 else if (!(desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
5929 {
5930 /* Tests show surfaces without memory flags get these flags added
5931 * right after creation. */
5932 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
5933 }
5934 }
5935
5936 if ((desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
5937 == (DDSCAPS_OVERLAY | DDSCAPS_SYSTEMMEMORY))
5938 {
5939 WARN("System memory overlays are not allowed.\n");
5940 HeapFree(GetProcessHeap(), 0, texture);
5941 return DDERR_NOOVERLAYHW;
5942 }
5943
5944 if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
5945 {
5946 /*
5947 * The ddraw RGB device allows to use system memory surfaces as rendering target.
5948 * This does not cause problems because the RGB device does software rasterization
5949 * though it will fail with hardware accelerated ddraw. In order to be partially
5950 * compatible with games requesting explicitly the RGB device, we ignore the
5951 * specified location and try to create rendering targets in video memory if
5952 * possible.
5953 */
5954 if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
5955 SUCCEEDED(hr = wined3d_check_device_format(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
5956 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_RENDERTARGET,
5957 WINED3D_RTYPE_SURFACE, wined3d_desc.format)))
5958 {
5959 FIXME("Application wants to create rendering target in system memory, using video memory instead\n");
5960 wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET;
5961 }
5962 else
5963 wined3d_desc.pool = WINED3D_POOL_SYSTEM_MEM;
5964 }
5965 else
5966 {
5967 if (desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5968 wined3d_desc.usage |= WINED3DUSAGE_TEXTURE;
5969 if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
5970 wined3d_desc.usage |= WINED3DUSAGE_DEPTHSTENCIL;
5971 else if (desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
5972 wined3d_desc.usage |= WINED3DUSAGE_RENDERTARGET;
5973
5974 if (desc->ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE))
5975 {
5976 wined3d_desc.pool = WINED3D_POOL_MANAGED;
5977 /* Managed textures have the system memory flag set. */
5978 desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
5979 }
5980 else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5981 {
5982 /* Videomemory adds localvidmem. This is mutually exclusive with
5983 * systemmemory and texturemanage. */
5984 desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
5985 wined3d_desc.usage |= WINED3DUSAGE_DYNAMIC;
5986 }
5987 }
5988
5989 /* If the surface is of the 'ALLOCONLOAD' type, ignore the LPSURFACE
5990 * field. Frank Herbert's Dune specifies a NULL pointer for lpSurface. */
5991 if ((desc->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD) || !desc->lpSurface)
5992 desc->dwFlags &= ~DDSD_LPSURFACE;
5993 if (desc->dwFlags & DDSD_LPSURFACE)
5994 {
5995 if (wined3d_desc.pool != WINED3D_POOL_SYSTEM_MEM)
5996 {
5997 WARN("User memory surfaces should be in the system memory pool.\n");
5998 HeapFree(GetProcessHeap(), 0, texture);
5999 return DDERR_INVALIDCAPS;
6000 }
6001
6002 if (version < 4)
6003 {
6004 WARN("User memory surfaces not supported before version 4.\n");
6005 HeapFree(GetProcessHeap(), 0, texture);
6006 return DDERR_INVALIDPARAMS;
6007 }
6008
6009 if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6010 {
6011 if (version != 4 && (desc->dwFlags & DDSD_PITCH))
6012 {
6013 WARN("Pitch specified on a compressed user memory surface.\n");
6014 HeapFree(GetProcessHeap(), 0, texture);
6015 return DDERR_INVALIDPARAMS;
6016 }
6017
6018 if (!(desc->dwFlags & (DDSD_LINEARSIZE | DDSD_PITCH)))
6019 {
6020 WARN("Compressed user memory surfaces should explicitly specify the linear size.\n");
6021 HeapFree(GetProcessHeap(), 0, texture);
6022 return DDERR_INVALIDPARAMS;
6023 }
6024
6025 if ((desc->dwFlags & DDSD_LINEARSIZE)
6026 && desc->u1.dwLinearSize < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
6027 wined3d_desc.format, wined3d_desc.width) * ((desc->dwHeight + 3) / 4))
6028 {
6029 WARN("Invalid linear size %u specified.\n", desc->u1.dwLinearSize);
6030 HeapFree(GetProcessHeap(), 0, texture);
6031 return DDERR_INVALIDPARAMS;
6032 }
6033 }
6034 else
6035 {
6036 if (!(desc->dwFlags & DDSD_PITCH))
6037 {
6038 WARN("User memory surfaces should explicitly specify the pitch.\n");
6039 HeapFree(GetProcessHeap(), 0, texture);
6040 return DDERR_INVALIDPARAMS;
6041 }
6042
6043 if (desc->u1.lPitch < wined3d_calculate_format_pitch(ddraw->wined3d, WINED3DADAPTER_DEFAULT,
6044 wined3d_desc.format, wined3d_desc.width) || desc->u1.lPitch & 3)
6045 {
6046 WARN("Invalid pitch %u specified.\n", desc->u1.lPitch);
6047 HeapFree(GetProcessHeap(), 0, texture);
6048 return DDERR_INVALIDPARAMS;
6049 }
6050
6051 pitch = desc->u1.lPitch;
6052 }
6053 }
6054
6055 if (((desc->dwFlags & DDSD_CKDESTOVERLAY)
6056 && desc->u3.ddckCKDestOverlay.dwColorSpaceLowValue != desc->u3.ddckCKDestOverlay.dwColorSpaceHighValue)
6057 || ((desc->dwFlags & DDSD_CKDESTBLT)
6058 && desc->ddckCKDestBlt.dwColorSpaceLowValue != desc->ddckCKDestBlt.dwColorSpaceHighValue)
6059 || ((desc->dwFlags & DDSD_CKSRCOVERLAY)
6060 && desc->ddckCKSrcOverlay.dwColorSpaceLowValue != desc->ddckCKSrcOverlay.dwColorSpaceHighValue)
6061 || ((desc->dwFlags & DDSD_CKSRCBLT)
6062 && desc->ddckCKSrcBlt.dwColorSpaceLowValue != desc->ddckCKSrcBlt.dwColorSpaceHighValue))
6063 {
6064 WARN("Range color keys not supported, returning DDERR_NOCOLORKEYHW.\n");
6065 HeapFree(GetProcessHeap(), 0, texture);
6066 return DDERR_NOCOLORKEYHW;
6067 }
6068
6069 if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
6070 wined3d_desc.usage |= WINED3DUSAGE_OVERLAY;
6071
6072 if (desc->ddsCaps.dwCaps & DDSCAPS_OWNDC)
6073 wined3d_desc.usage |= WINED3DUSAGE_OWNDC;
6074
6075 if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6076 {
6077 wined3d_desc.resource_type = WINED3D_RTYPE_CUBE_TEXTURE;
6078 layers = 6;
6079 }
6080 else
6081 {
6082 wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE;
6083 layers = 1;
6084 }
6085
6086 /* Some applications assume surfaces will always be mapped at the same
6087 * address. Some of those also assume that this address is valid even when
6088 * the surface isn't mapped, and that updates done this way will be
6089 * visible on the screen. The game Nox is such an application,
6090 * Commandos: Behind Enemy Lines is another. We set
6091 * WINED3D_SURFACE_PIN_SYSMEM because of this. */
6092 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, levels,
6093 WINED3D_SURFACE_PIN_SYSMEM, NULL, texture, &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
6094 {
6095 WARN("Failed to create wined3d texture, hr %#x.\n", hr);
6096 HeapFree(GetProcessHeap(), 0, texture);
6097 return hr_ddraw_from_wined3d(hr);
6098 }
6099
6100 resource = wined3d_texture_get_sub_resource(wined3d_texture, 0);
6101 root = wined3d_resource_get_parent(resource);
6102 root->wined3d_texture = wined3d_texture;
6103 root->is_complex_root = TRUE;
6104 texture->root = root;
6105
6106 if (desc->dwFlags & DDSD_CKDESTOVERLAY)
6107 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
6108 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
6109 if (desc->dwFlags & DDSD_CKDESTBLT)
6110 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
6111 (struct wined3d_color_key *)&desc->ddckCKDestBlt);
6112 if (desc->dwFlags & DDSD_CKSRCOVERLAY)
6113 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
6114 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
6115 if (desc->dwFlags & DDSD_CKSRCBLT)
6116 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
6117 (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
6118
6119 for (i = 0; i < layers; ++i)
6120 {
6121 attach = &root->complex_array[layers - 1 - i];
6122
6123 for (j = 0; j < levels; ++j)
6124 {
6125 resource = wined3d_texture_get_sub_resource(wined3d_texture, i * levels + j);
6126 mip = wined3d_resource_get_parent(resource);
6127 mip_desc = &mip->surface_desc;
6128
6129 if (j)
6130 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
6131 else
6132 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
6133
6134 if (mip_desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6135 {
6136 mip_desc->ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
6137
6138 switch (i)
6139 {
6140 case WINED3D_CUBEMAP_FACE_POSITIVE_X:
6141 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
6142 break;
6143 case WINED3D_CUBEMAP_FACE_NEGATIVE_X:
6144 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX;
6145 break;
6146 case WINED3D_CUBEMAP_FACE_POSITIVE_Y:
6147 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY;
6148 break;
6149 case WINED3D_CUBEMAP_FACE_NEGATIVE_Y:
6150 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY;
6151 break;
6152 case WINED3D_CUBEMAP_FACE_POSITIVE_Z:
6153 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ;
6154 break;
6155 case WINED3D_CUBEMAP_FACE_NEGATIVE_Z:
6156 mip_desc->ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ;
6157 break;
6158 }
6159
6160 }
6161
6162 if (mip == root)
6163 continue;
6164
6165 *attach = mip;
6166 attach = &mip->complex_array[0];
6167 }
6168 }
6169
6170 if ((desc->dwFlags & DDSD_LPSURFACE) && FAILED(hr = wined3d_texture_update_desc(wined3d_texture,
6171 wined3d_desc.width, wined3d_desc.height, wined3d_desc.format,
6172 WINED3D_MULTISAMPLE_NONE, 0, desc->lpSurface, pitch)))
6173 {
6174 ERR("Failed to set surface memory, hr %#x.\n", hr);
6175 goto fail;
6176 }
6177
6178 if (desc->dwFlags & DDSD_BACKBUFFERCOUNT)
6179 {
6180 unsigned int count = desc->u5.dwBackBufferCount;
6181 struct ddraw_surface *last = root;
6182
6183 attach = &last->complex_array[0];
6184 for (i = 0; i < count; ++i)
6185 {
6186 if (!(texture = HeapAlloc(GetProcessHeap(), 0, sizeof(*texture))))
6187 {
6188 hr = E_OUTOFMEMORY;
6189 goto fail;
6190 }
6191
6192 texture->version = version;
6193 texture->surface_desc = root->surface_desc;
6194 desc = &texture->surface_desc;
6195
6196 /* Only one surface in the flipping chain is a back buffer, one is
6197 * a front buffer, the others are just flippable surfaces. */
6198 desc->ddsCaps.dwCaps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER
6199 | DDSCAPS_BACKBUFFER);
6200 if (!i)
6201 desc->ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
6202 desc->u5.dwBackBufferCount = 0;
6203
6204 if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, 1,
6205 WINED3D_SURFACE_PIN_SYSMEM, NULL, texture, &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
6206 {
6207 HeapFree(GetProcessHeap(), 0, texture);
6208 hr = hr_ddraw_from_wined3d(hr);
6209 goto fail;
6210 }
6211
6212 resource = wined3d_texture_get_sub_resource(wined3d_texture, 0);
6213 last = wined3d_resource_get_parent(resource);
6214 last->wined3d_texture = wined3d_texture;
6215 texture->root = last;
6216
6217 if (desc->dwFlags & DDSD_CKDESTOVERLAY)
6218 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTOVERLAY,
6219 (struct wined3d_color_key *)&desc->u3.ddckCKDestOverlay);
6220 if (desc->dwFlags & DDSD_CKDESTBLT)
6221 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_DESTBLT,
6222 (struct wined3d_color_key *)&desc->ddckCKDestBlt);
6223 if (desc->dwFlags & DDSD_CKSRCOVERLAY)
6224 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCOVERLAY,
6225 (struct wined3d_color_key *)&desc->ddckCKSrcOverlay);
6226 if (desc->dwFlags & DDSD_CKSRCBLT)
6227 wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
6228 (struct wined3d_color_key *)&desc->ddckCKSrcBlt);
6229
6230 *attach = last;
6231 attach = &last->complex_array[0];
6232 }
6233 *attach = root;
6234 }
6235
6236 if (surface_desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
6237 ddraw->primary = root;
6238 *surface = root;
6239
6240 return DD_OK;
6241
6242 fail:
6243 if (version == 7)
6244 IDirectDrawSurface7_Release(&root->IDirectDrawSurface7_iface);
6245 else if (version == 4)
6246 IDirectDrawSurface4_Release(&root->IDirectDrawSurface4_iface);
6247 else
6248 IDirectDrawSurface_Release(&root->IDirectDrawSurface_iface);
6249
6250 return hr;
6251 }
6252
6253 void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, struct ddraw_texture *texture,
6254 struct wined3d_surface *wined3d_surface, const struct wined3d_parent_ops **parent_ops)
6255 {
6256 DDSURFACEDESC2 *desc = &surface->surface_desc;
6257 struct wined3d_resource_desc wined3d_desc;
6258 unsigned int version = texture->version;
6259
6260 surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl;
6261 surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl;
6262 surface->IDirectDrawSurface3_iface.lpVtbl = &ddraw_surface3_vtbl;
6263 surface->IDirectDrawSurface2_iface.lpVtbl = &ddraw_surface2_vtbl;
6264 surface->IDirectDrawSurface_iface.lpVtbl = &ddraw_surface1_vtbl;
6265 surface->IDirectDrawGammaControl_iface.lpVtbl = &ddraw_gamma_control_vtbl;
6266 surface->IDirect3DTexture2_iface.lpVtbl = &d3d_texture2_vtbl;
6267 surface->IDirect3DTexture_iface.lpVtbl = &d3d_texture1_vtbl;
6268 surface->iface_count = 1;
6269 surface->version = version;
6270 surface->ddraw = ddraw;
6271
6272 if (version == 7)
6273 {
6274 surface->ref7 = 1;
6275 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface7_iface;
6276 }
6277 else if (version == 4)
6278 {
6279 surface->ref4 = 1;
6280 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface4_iface;
6281 }
6282 else
6283 {
6284 surface->ref1 = 1;
6285 surface->texture_outer = (IUnknown *)&surface->IDirectDrawSurface_iface;
6286 }
6287
6288 *desc = texture->surface_desc;
6289 wined3d_resource_get_desc(wined3d_surface_get_resource(wined3d_surface), &wined3d_desc);
6290 desc->dwWidth = wined3d_desc.width;
6291 desc->dwHeight = wined3d_desc.height;
6292 surface->first_attached = surface;
6293
6294 if (format_is_compressed(&desc->u4.ddpfPixelFormat))
6295 {
6296 if (desc->dwFlags & DDSD_LPSURFACE)
6297 desc->u1.dwLinearSize = ~0u;
6298 else
6299 desc->u1.dwLinearSize = wined3d_surface_get_pitch(wined3d_surface) * ((desc->dwHeight + 3) / 4);
6300 desc->dwFlags |= DDSD_LINEARSIZE;
6301 desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_PITCH);
6302 }
6303 else
6304 {
6305 if (!(desc->dwFlags & DDSD_LPSURFACE))
6306 desc->u1.lPitch = wined3d_surface_get_pitch(wined3d_surface);
6307 desc->dwFlags |= DDSD_PITCH;
6308 desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_LINEARSIZE);
6309 }
6310 desc->lpSurface = NULL;
6311
6312 wined3d_surface_incref(wined3d_surface);
6313 surface->wined3d_surface = wined3d_surface;
6314 *parent_ops = &ddraw_surface_wined3d_parent_ops;
6315
6316 wined3d_private_store_init(&surface->private_store);
6317 }
6318
6319 static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
6320 {
6321 struct ddraw_surface *surface = parent;
6322
6323 /* If the surface reference count drops to zero, we release our reference
6324 * to the view, but don't clear the pointer yet, in case e.g. a
6325 * GetRenderTarget() call brings the surface back before the view is
6326 * actually destroyed. When the view is destroyed, we need to clear the
6327 * pointer, or a subsequent surface AddRef() would reference it again.
6328 *
6329 * This is safe because as long as the view still has a reference to the
6330 * texture, the surface is also still alive, and we're called before the
6331 * view releases that reference. */
6332 surface->wined3d_rtv = NULL;
6333 }
6334
6335 static const struct wined3d_parent_ops ddraw_view_wined3d_parent_ops =
6336 {
6337 view_wined3d_object_destroyed,
6338 };
6339
6340 struct wined3d_rendertarget_view *ddraw_surface_get_rendertarget_view(struct ddraw_surface *surface)
6341 {
6342 HRESULT hr;
6343
6344 if (surface->wined3d_rtv)
6345 return surface->wined3d_rtv;
6346
6347 if (FAILED(hr = wined3d_rendertarget_view_create_from_surface(surface->wined3d_surface,
6348 surface, &ddraw_view_wined3d_parent_ops, &surface->wined3d_rtv)))
6349 {
6350 ERR("Failed to create rendertarget view, hr %#x.\n", hr);
6351 return NULL;
6352 }
6353
6354 return surface->wined3d_rtv;
6355 }